summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHobbist2024-03-14 13:04:26 +0530
committerHobbist2024-03-14 13:04:26 +0530
commit10a163269ffd184c30b36e3863a65004f47404ca (patch)
tree9b3fb55487ac9ba856379d4570ce78b972e0666d
parent7310a1f9e653f34b5fc83ea7e7013c405bdafb59 (diff)
downloadpyvnt-10a163269ffd184c30b36e3863a65004f47404ca.tar.gz
pyvnt-10a163269ffd184c30b36e3863a65004f47404ca.tar.bz2
pyvnt-10a163269ffd184c30b36e3863a65004f47404ca.zip
initial commit
-rw-r--r--.gitignore4
-rw-r--r--README.md226
-rwxr-xr-xTesting/test.py24
-rwxr-xr-xTesting/test_pyvnt.py37
-rw-r--r--assets/output.txt30
-rwxr-xr-xpyvnt/DictionaryElement/__init__.py0
-rw-r--r--pyvnt/DictionaryElement/__pycache__/__init__.cpython-311.pycbin0 -> 186 bytes
-rw-r--r--pyvnt/DictionaryElement/__pycache__/foamDS.cpython-311.pycbin0 -> 5061 bytes
-rw-r--r--pyvnt/DictionaryElement/__pycache__/keyData.cpython-311.pycbin0 -> 5928 bytes
-rw-r--r--pyvnt/DictionaryElement/__pycache__/showTree.cpython-311.pycbin0 -> 1311 bytes
-rwxr-xr-xpyvnt/DictionaryElement/foamDS.py137
-rwxr-xr-xpyvnt/DictionaryElement/keyData.py167
-rwxr-xr-xpyvnt/DictionaryElement/obj_constructor.py26
-rwxr-xr-xpyvnt/DictionaryElement/showTree.py30
-rwxr-xr-xpyvnt/Reference/__init__.py0
-rw-r--r--pyvnt/Reference/__pycache__/__init__.cpython-311.pycbin0 -> 178 bytes
-rw-r--r--pyvnt/Reference/__pycache__/basic.cpython-311.pycbin0 -> 12748 bytes
-rw-r--r--pyvnt/Reference/__pycache__/errorClasses.cpython-311.pycbin0 -> 4847 bytes
-rwxr-xr-xpyvnt/Reference/basic.py269
-rwxr-xr-xpyvnt/Reference/errorClasses.py65
-rwxr-xr-xpyvnt/__init__.py4
-rw-r--r--pyvnt/__pycache__/__init__.cpython-311.pycbin0 -> 373 bytes
-rwxr-xr-xpyvnt/test/treeTest.py11
-rw-r--r--readme.md1
-rwxr-xr-xsetPackage.py16
-rwxr-xr-xsetup.py33
26 files changed, 1079 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0e93bb2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+env
+build/
+dist/
+pyvnt.egg-info \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..270c880
--- /dev/null
+++ b/README.md
@@ -0,0 +1,226 @@
+# PyVnt : Python Venturial Node Trees
+
+PyVnt aims to represent OpenFOAM files in form of Node trees using python.
+
+OpenFOAM case files are primarity in `.txt` format, which makes them difficult to parse and automate the process of case file generation using a GUI. PyVnt aims to ease this process by handling the data in the OpenFOAM case files and store then in the form of Node trees using python.
+
+This project is an extension of the [Venturial](https://github.com/FOSSEE/venturial) project as currently there is no middleware to handle the data generated by Venturial outside of Blender. PyVnt aims to be the middleware between the GUI application and the OpenFOAM case files.
+
+PyVnt seeks to provide a medium to handle data from OpenFOAM case files in python, acting as a middleware for any other python based application focused on easing the process of OpenFOAM case generation.
+
+## Features
+
+The main features fo pyvnt package are:
+
+1. Make Node trees that mimic the scructure of OpenFOAM Dictionary data structure.
+2. Map multiple values to a single key as it is done in a OpenFOAM dictionary.
+3. Dynamically edit the Node trees once they are created.
+
+
+## Installation
+
+1. Clone the repository.
+```bash
+$ git clone https://github.com/FOSSEE/pyvnt.git
+```
+2. Create a python virtual environment in which you want to install the python package
+
+3. Run the `setup.py` script inside a python virtual environment to build the python package from the source files
+
+```bash
+$ python setup.py sdist bdist_wheel
+```
+
+4. Install the python package from the build files using `setup.py`
+
+```bash
+$ python setup.py install
+```
+
+
+5. import `pyvnt` in your script to use it.
+
+
+
+## Venturial Node-Trees
+
+There are different classes in the package for different kinds of data in OpenFOAM:
+
+- `ValueProperty` class is used to represent basic values. There are three children classes under `ValueProperty`:
+ - `EnumProp` class is used to represent string values. The reason for it being an enum is that the fields that have string values usually have a vew options for the string values, and a enum helps to reinforce those options and prevent the user from entering incorrect values.
+ - `IntProperty` class is used to represent Integer values.
+ - `FloatProperty` class is used to represent Floating point values
+
+- `KeyData` class is used to store keys for the OpenFOAM distionary data types
+
+- `Foam` class is used to represent the OpenFOAM dictionary data type.
+
+Here is a detailed comparisions of a OpenFOAM dictionary and a pyvnt Node tree:
+
+The example OpenFOAM dictionary is written on the left, and the Node created in pyvnt is displayed in the right, with the object type mentioned in brackets beside the name of the value.
+
+<table border="0">
+ <tr>
+ <th><b>OpenFOAM dictionary</b></th>
+ <th><b>PyVnt Node Tree</b></th>
+ </tr>
+ <tr>
+ <td>
+<pre>
+solvers
+{
+ p
+ {
+ solver PCG, BNR;
+ preconditioner DIC;
+ tolerance 1e-06;
+ relTol 0.05;
+ }
+}
+</pre>
+ </td>
+ <td>
+<pre>
+solvers(Foam)
+└── p(Foam)
+ {
+ solver(KeyData) : PCG(EnumProp), BNR(EnumProp)
+ preconditioner(KeyData) : DIC(EnumProp),
+ tolerance(KeyData) : 1e-06(FloatProperty),
+ relTol(KeyData) : 0.05(FloatProperty),
+ }
+</pre>
+ </td>
+ </tr>
+</table>
+
+As shown above, the `Foam` and `KeyData` classes are used to represent the basic elements of the OpenFOAM Dictionary data structure. While the `ValueProperty` classe and its children classes are used to represent the basic property values in OpenFOAM.
+
+## Sample Use Case
+
+Here is an example OpenFOAM use case file that we will use as a reference.
+
+```text
+fvSolutions.txt
+
+FoamFile
+{
+ version 2.0;
+ class dictionary;
+ format ascii;
+}
+
+solvers
+{
+ p
+ {
+ solver PCG, BNR;
+ preconditioner DIC;
+ tolerance 1e-06;
+ relTol 0.05;
+ }
+
+ pFinal
+ {
+ $p;
+ relTol 0;
+ }
+
+ U
+ {
+ solver smoothSolver;
+ smoother symGaussSeidel;
+ tolerance 1e-05;
+ relTol 0;
+ }
+}
+
+PISO
+{
+ nCorrectors 2;
+ nNonOrthogonalCorrectors 0;
+ pRefCell 0;
+ pRefValue 0;
+}
+```
+
+
+
+Here is how a sample code would look like that would build this file inside pyvnt:
+
+```py
+# testfile.py
+
+from pyvnt import *
+
+head = Foam('fvSolutions')
+
+sl = Foam('solvers', parent = head)
+
+s = KeyData('solver', EnumProp('val1', items={'PCG', 'PBiCG', 'PBiCGStab'}, default='PCG'))
+pc = KeyData('preconditioner', EnumProp('val1', items={'DIC', 'DILU', 'FDIC'}, default='DIC'))
+tol = KeyData('tolerance', PropertyFloat('val1', minimum=0, maximum=1000, default=1e-06))
+rt = KeyData('relTol', PropertyFloat('val1', minimum=0, maximum=100, default=0.05))
+
+p = Foam('p', sl, None, pc, s, tol, rt)
+
+relTol2 = KeyData('relTol', PropertyFloat('val1', minimum=0, maximum=100, default=0))
+
+pf = Foam('pFinal', sl, None, relTol2)
+
+sol2 = KeyData('solver', EnumProp('val1', items={'smoothSolver'}, default='smoothSolver'))
+sm = KeyData('smoother', EnumProp('val1', items={'symGaussSeidel', 'gaussSeidel'}, default = 'symGaussSeidel'))
+tol2 = KeyData('tolerance', PropertyFloat('val1', minimum=0, maximum=1000, default=1e-05))
+relTol3 = KeyData('relTol', PropertyFloat('val1', minimum=0, maximum=100, default=0))
+
+u = Foam('U', sl, None, sol2, sm,
+ tol2, relTol3)
+
+ncorr = KeyData('nCorrectors', PropertyInt('int_prop_1', minimum=0, maximum=100, default=2))
+nnoc = KeyData('nNonOrthogonalCorrectors', PropertyInt('int_prop_2', minimum=0, maximum=100, default=0))
+prc = KeyData('pRefCell', PropertyInt('int_prop_3', minimum=0, maximum=100, default=0))
+prv = KeyData('pRefValue', PropertyInt('int_prop_4', minimum=0, maximum=100, default=0))
+
+
+piso = Foam('PISO', head, None, ncorr,
+ nnoc, prc, prv)
+
+showTree(head)
+
+```
+
+The resultant tree generated using the above code will look like the following:
+
+```bash
+$ python testfile.py
+
+fvSolutions
+├── solvers
+│ ├── p
+│ │ {
+│ │ preconditioner : DIC,
+│ │ solver : PCG,
+│ │ tolerance : 1e-06,
+│ │ relTol : 0.05,
+│ │ }
+│ ├── pFinal
+│ │ {
+│ │ relTol : 0,
+│ │ }
+│ └── U
+│ {
+│ solver : smoothSolver,
+│ smoother : symGaussSeidel,
+│ tolerance : 1e-05,
+│ relTol : 0,
+│ }
+└── PISO
+ {
+ nCorrectors : 2,
+ nNonOrthogonalCorrectors : 0,
+ pRefCell : 0,
+ pRefValue : 0,
+ }
+```
+
+ \ No newline at end of file
diff --git a/Testing/test.py b/Testing/test.py
new file mode 100755
index 0000000..e98b25a
--- /dev/null
+++ b/Testing/test.py
@@ -0,0 +1,24 @@
+from pyvnt.DictionaryElement.foamDS import Foam
+from pyvnt.DictionaryElement.keyData import KeyData
+
+def obj_constructor(name: str, parent = None, children: [] = None, *args):
+ '''
+ Function to create a new node object with the given name
+
+ Parameter:
+ name: Name of the Node that is to be created
+ parent: Parent Node of the current Node (Optional)
+ children: List of the children node(s) of the current Node (Optional)
+ '''
+
+ if children != None and args != None:
+ raise Exception("Both children and args cannot be given at the same time")
+ elif args == None:
+ return Foam(name, parent, children)
+ elif children == None:
+ return KeyData(name, parent, *args)
+ else:
+ raise Exception("Invalid arguments given")
+
+obj = obj_constructor("test_head")
+print(obj) \ No newline at end of file
diff --git a/Testing/test_pyvnt.py b/Testing/test_pyvnt.py
new file mode 100755
index 0000000..fbdae29
--- /dev/null
+++ b/Testing/test_pyvnt.py
@@ -0,0 +1,37 @@
+from pyvnt import *
+from anytree import RenderTree, AsciiStyle
+
+'''
+prop1 = EnumProp('val1', items={'PCG', 'PBiCG', 'PBiCGStab'}, default='PCG')
+prop2 = EnumProp('val2', items={'PCG', 'PBiCG', 'PBiCGStab'}, default='PBiCG')
+'''
+
+# set up automated tests for CI/CD in github
+
+# test for KeyData and Foam classes
+'''
+key1 = KeyData('solver', prop1, prop2)
+print(key1.giveVal())
+head = Foam("test_head",None, None)
+
+# head.appendDict(args)
+
+child1 = Foam('test_child', head, None)
+child2 = Foam('test_child2', child1, None, key1)
+child3 = Foam('test_child3', child1, None, key1)
+'''
+
+# Display tests
+'''
+print(head)
+showTree(head)
+print(RenderTree(child1).by_attr())
+'''
+
+# Test for Keydata class singularily
+'''
+key1 = KeyData('solver', prop1)
+print(key1)
+
+'''
+
diff --git a/assets/output.txt b/assets/output.txt
new file mode 100644
index 0000000..a455214
--- /dev/null
+++ b/assets/output.txt
@@ -0,0 +1,30 @@
+❯ python readFile_test.py
+fvSolutions
+├── solvers
+│ ├── p
+│ │ {
+│ │ preconditioner : DIC,
+│ │ solver : PCG,
+│ │ tolerance : 1e-06,
+│ │ relTol : 0.05,
+│ │ }
+│ ├── pFinal
+│ │ {
+│ │ relTol : 0,
+│ │ }
+│ └── U
+│ {
+│ solver : smoothSolver,
+│ smoother : symGaussSeidel,
+│ tolerance : 1e-05,
+│ relTol : 0,
+│ }
+└── PISO
+ {
+ nCorrectors : 2,
+ nNonOrthogonalCorrectors : 0,
+ pRefCell : 0,
+ pRefValue : 0,
+ }
+
+
diff --git a/pyvnt/DictionaryElement/__init__.py b/pyvnt/DictionaryElement/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/pyvnt/DictionaryElement/__init__.py
diff --git a/pyvnt/DictionaryElement/__pycache__/__init__.cpython-311.pyc b/pyvnt/DictionaryElement/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..e55751d
--- /dev/null
+++ b/pyvnt/DictionaryElement/__pycache__/__init__.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/DictionaryElement/__pycache__/foamDS.cpython-311.pyc b/pyvnt/DictionaryElement/__pycache__/foamDS.cpython-311.pyc
new file mode 100644
index 0000000..215e032
--- /dev/null
+++ b/pyvnt/DictionaryElement/__pycache__/foamDS.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/DictionaryElement/__pycache__/keyData.cpython-311.pyc b/pyvnt/DictionaryElement/__pycache__/keyData.cpython-311.pyc
new file mode 100644
index 0000000..d957d3d
--- /dev/null
+++ b/pyvnt/DictionaryElement/__pycache__/keyData.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/DictionaryElement/__pycache__/showTree.cpython-311.pyc b/pyvnt/DictionaryElement/__pycache__/showTree.cpython-311.pyc
new file mode 100644
index 0000000..4971a29
--- /dev/null
+++ b/pyvnt/DictionaryElement/__pycache__/showTree.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/DictionaryElement/foamDS.py b/pyvnt/DictionaryElement/foamDS.py
new file mode 100755
index 0000000..9a3ca5c
--- /dev/null
+++ b/pyvnt/DictionaryElement/foamDS.py
@@ -0,0 +1,137 @@
+from anytree import Node, RenderTree, AsciiStyle, NodeMixin
+from typing import Any, Type
+from pyvnt.DictionaryElement.keyData import KeyData
+from pyvnt.Reference.errorClasses import *
+
+'''
+Criteria for classes:
+1. any attributes should be added to the class only through the constructor, and not through the object
+2. the attributes should be accessible only through the object
+3. the attributed should not be accesible through . operator -- done by name mangling(__var)
+'''
+
+class Foam(NodeMixin):
+ """
+ Class to define nodes of the tree
+
+ Contructor Parameters:
+ name: Name of the Node object
+ parent: Parent Node of the current Node (Optional)
+ children: List of the children node(s) of the current Node (Optional)
+ """
+
+ # __slots__ = ('name', 'parent', 'children', 'data')
+
+ def __init__(self, name: str, parent = None, children: [] = None, *args: KeyData):
+
+ super(Foam, self).__init__()
+ # self._privateDict = kwargs
+ self.name = name
+
+ self.data = list(args)
+
+ if parent == None or parent.data == []:
+ self.parent = parent
+ else:
+ raise LeafNodeError(self)
+
+ if children:
+ self.children = children
+
+
+ def __getattr__(self, key):
+ """
+ Prevents access to attributes which are not in _privateDict
+ """
+ accepted_keys = ['name', 'parent', 'children']
+ if key in accepted_keys:
+ return super().__getattr__(key)
+ else:
+ raise AttributeError(key)
+
+
+ # def __setattr__(self, key, value):
+ # super().__setattr__(key, value)
+
+
+ # def dispTree(self):
+ # '''
+ # Function to output the entire tree in the terminal starting from the current node object
+ # '''
+ # for pre, fill, node in RenderTree(self):
+ # treestr = u"%s%s" % (pre, node.name)
+ # s = ""
+
+
+
+
+ # print(treestr.ljust(8), s)
+
+
+ def addChild(self, node):
+ '''
+ Function to add a child node to the current node
+
+ Parameter:
+ node: Node object to be added as a child
+ '''
+ self.children += (node, )
+
+
+ def setParent(self, node):
+ '''
+ Function to set the parent node to the current node
+
+ Parameter:
+ node: Node object to be added as a child
+ '''
+ self.parent = node
+
+ def __repr__(self):
+ res_str = f"Foam("
+ for key, val in self.__dict__.items():
+ res_str = res_str + f"{key} : {val}, "
+ res_str = res_str + ")"
+ return res_str
+
+ def getChild(self, val: str):
+ '''
+ Function to find a child node with the given attribute
+
+ Parameter:
+ val: Name of the Node that is bein searched for
+ '''
+ return find_by_attr(self, val, maxlevel = 2)
+
+ def addData(self, data: KeyData, pos: int = None):
+ '''
+ Function to add KeyData attributes to the existing Node
+ '''
+
+ if pos != None:
+ self.data.insert(data, pos)
+ else:
+ self.data.append(data)
+
+ def removeData(self, data: KeyData):
+ '''
+ Function to remove a keydata attribute from the node
+ '''
+
+ try:
+ self.data.pop(data)
+ except:
+ raise AttributeError(f"{data.name} does not exist in this node")
+
+ def reorderData(self, data: KeyData, pos: int):
+ '''
+ Function to reorder the data in the node
+ '''
+
+ try:
+ self.data.pop(data)
+ self.data.insert(data, pos)
+ except:
+ raise AttributeError(f"{data.name} does not exist in this node")
+
+
diff --git a/pyvnt/DictionaryElement/keyData.py b/pyvnt/DictionaryElement/keyData.py
new file mode 100755
index 0000000..39c5c7e
--- /dev/null
+++ b/pyvnt/DictionaryElement/keyData.py
@@ -0,0 +1,167 @@
+from abc import ABC, abstractmethod
+from collections import OrderedDict
+from anytree import NodeMixin
+from pyvnt.Reference.basic import *
+
+
+'''
+Criteria for classes:
+1. any attributes should be added to the class only through the constructor or edit function, and not through the object
+2. the attributes should be editable only through the object
+3. the attributed should not be accesible through . operator -- done by name mangling(__var)
+'''
+
+class KeyParent(ABC):
+ '''
+ Abstract class to make sure that attributes cannot be inserted into the child class directly
+ Do not make objects of this class
+ '''
+
+ def __init__(self, name: str = "Parent"):
+ self.__dict__['name'] = name
+
+ @abstractmethod
+ def instance_restricted(self):
+ pass
+
+# TODO: prevent access of attributes from outside the class -- done
+# Currently the attributes can be edited from outside the class, which should not be possible
+# TODO: Modify such that constructor takes in no attribute by default. After making the constructor, use a method to insert attributes -- done
+class KeyData(KeyParent):
+
+ def instance_restricted(self):
+ pass
+
+ # def old__init__(self, name=None, **kwargs: ValueProperty): # old init method,
+ # super(KeyData, self).__init__(name)
+ # self.__dict__.update(kwargs)
+ # # self.__toggle_freeze()
+
+ def __init__(self, name: str = None, *args: ValueProperty):
+ super(KeyData, self).__init__(name)
+
+ tmp = {}
+ for e in args:
+ tmp[e._ValueProperty__name] = e
+
+ self._privateDict = OrderedDict(tmp)
+
+
+ def __getattr__(self, key):
+ """
+ Prevents access to attributes which are not in _privateDict
+ """
+ if key in self._privateDict.keys():
+ return self._privateDict[key]
+ else:
+ raise AttributeError(key)
+
+ def __setattr__(self, key, value):
+ """
+ Prevents Creation of new attributes but allows editing existing ones -- commented code
+
+ Prevents setting of attributes except _privateDict
+ """
+
+ if( key == '_privateDict'):
+ super().__setattr__(key,value)
+ else :
+ raise AttributeError(key)
+
+ def appendVal(self, key: "str", val: ValueProperty):
+ self._privateDict[key] = val
+
+ """
+ # TODO: Take input of the object to be replaced or the obejct name instead of the variable name as the string. -- done in replaceVal2
+ This piece of code is here to remind devs about what not to do
+
+ def replaceVal(self, oldKey: str, newKey: str, newVal: ValueProperty):
+
+ if oldKey == newKey:
+ self.__dict__[newKey] = newVal
+ else:
+ if newKey != oldKey and newKey in self.__dict__.keys():
+ raise KeyRepeatError(newKey)
+ else:
+ replacement = {oldKey: newKey}
+ for k, v in list(self.__dict__.items()):
+ self.__dict__[replacement.get(k, k)] = self.__dict__.pop(k)
+ self.__dict__[newKey] = newVal
+
+
+ def replaceVal2(self, old: ValueProperty | str, new: ValueProperty):
+ if type(old) == str:
+ oldKey = old
+ else:
+ oldKey = old._ValueProperty__name
+
+ newKey = new._ValueProperty__name
+
+ if oldKey == newKey:
+ self.__dict__[newKey] = new
+ else:
+ if newKey != oldKey and newKey in self.__dict__.keys():
+ raise KeyRepeatError(newKey)
+ else:
+ replacement = {oldKey: newKey}
+ for k, v in list(self.__dict__.items()):
+ self.__dict__[replacement.get(k, k)] = self.__dict__.pop(k)
+ self.__dict__[newKey] = new
+ """
+
+ def replaceVal(self, old: ValueProperty | str, new: ValueProperty): # uses orderedDict instead of regular Dictionary
+ '''
+ Function to insert and edit values in the class object once it is created
+
+ Parameters:
+ old: object or name of object to be replaced
+ new: object of the new Data that is to be added
+
+ Returns:
+ None
+
+ '''
+ if type(old) == str:
+ oldKey = old
+ else:
+ oldKey = old._ValueProperty__name
+
+ newKey = new._ValueProperty__name
+
+ if oldKey == newKey:
+ self.__dict__[newKey] = new
+ else:
+ if newKey != oldKey and newKey in self.__dict__.keys():
+ raise KeyRepeatError(newKey)
+ else:
+ self._privateDict = OrderedDict([(newKey, new) if k == oldKey else (k, v) for k, v in self._privateDict.items()])
+
+ def delVal(self, key: str):
+ '''
+ Function to delete a given key from the object
+
+ Parameters:
+ key: name of the key to be deleted
+ '''
+ del self._privateDict[key]
+
+ def __repr__(self):
+ res_str = f"KeyData("
+ for key, val in self._privateDict.items():
+ res_str = res_str + f"{key} : {val}, "
+ res_str = res_str + ")"
+
+ return res_str
+
+ def giveVal(self):
+ '''
+ Function to get all the keys and values stored in the object in a text format
+ '''
+ res = f"{self.name} : "
+ for key, val in self._privateDict.items():
+ if key == 'name':
+ continue
+ else:
+ res = res + f"{val.giveVal()}, "
+
+ return res \ No newline at end of file
diff --git a/pyvnt/DictionaryElement/obj_constructor.py b/pyvnt/DictionaryElement/obj_constructor.py
new file mode 100755
index 0000000..2a1aecf
--- /dev/null
+++ b/pyvnt/DictionaryElement/obj_constructor.py
@@ -0,0 +1,26 @@
+from pyvnt.DictionaryElement.foamDS import Foam
+from pyvnt.DictionaryElement.keyData import KeyData
+
+# Function no longer needed
+# It is not available to use outside the package and the code is here just for future reference if needed
+
+def obj_constructor(name: str, parent = None, children: [] = None, *args):
+ '''
+ Function to create a new node object with the given name
+
+ Parameter:
+ name: Name of the Node that is to be created
+ parent: Parent Node of the current Node (Optional)
+ children: List of the children node(s) of the current Node (Optional)
+ '''
+
+ tmp = list(args)
+
+ if children != None and tmp != []:
+ raise Exception("Both children and args cannot be given at the same time")
+ elif tmp == [] and children == None:
+ return Foam(name, parent, children)
+ elif children == None:
+ return KeyData(name, parent, *args)
+ else:
+ raise Exception("Invalid arguments given") \ No newline at end of file
diff --git a/pyvnt/DictionaryElement/showTree.py b/pyvnt/DictionaryElement/showTree.py
new file mode 100755
index 0000000..096b1a1
--- /dev/null
+++ b/pyvnt/DictionaryElement/showTree.py
@@ -0,0 +1,30 @@
+from anytree import Node, RenderTree, AsciiStyle, NodeMixin
+from pyvnt.DictionaryElement.foamDS import Foam
+
+def showTree(head: Foam):
+ '''
+ Function to output the entire tree in the terminal starting from the current node object
+
+ Parameters:
+ head: Head Node of the tree to be printed. Must be of typpe `Foam`
+
+ Returns:
+ None
+ '''
+ for pre, fill, node in RenderTree(head):
+ print( "%s%s" % (pre, node.name))
+ attr = "%s{ \n" % (fill)
+ for d in node.data:
+
+ tmp_str = u"%s %s" % (fill, d.giveVal())
+ attr = attr + tmp_str + "\n"
+ attr = attr + "%s}"%(fill)
+
+ chk = "%s{ \n%s}" % (fill, fill)
+ if attr != chk:
+ print(attr)
+
+
+
+
+ \ No newline at end of file
diff --git a/pyvnt/Reference/__init__.py b/pyvnt/Reference/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/pyvnt/Reference/__init__.py
diff --git a/pyvnt/Reference/__pycache__/__init__.cpython-311.pyc b/pyvnt/Reference/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..64d59a9
--- /dev/null
+++ b/pyvnt/Reference/__pycache__/__init__.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/Reference/__pycache__/basic.cpython-311.pyc b/pyvnt/Reference/__pycache__/basic.cpython-311.pyc
new file mode 100644
index 0000000..c468e65
--- /dev/null
+++ b/pyvnt/Reference/__pycache__/basic.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/Reference/__pycache__/errorClasses.cpython-311.pyc b/pyvnt/Reference/__pycache__/errorClasses.cpython-311.pyc
new file mode 100644
index 0000000..dc4319a
--- /dev/null
+++ b/pyvnt/Reference/__pycache__/errorClasses.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/Reference/basic.py b/pyvnt/Reference/basic.py
new file mode 100755
index 0000000..c4a2c93
--- /dev/null
+++ b/pyvnt/Reference/basic.py
@@ -0,0 +1,269 @@
+from dataclasses import dataclass, replace, field
+from typing import Any
+import enum
+from abc import ABC, abstractmethod
+from pyvnt.Reference.errorClasses import *
+
+# Property Classes
+
+class ValueProperty(ABC):
+ '''
+ Abstract parent class for all the property classes
+
+ Do not create oobject of this class
+ '''
+ __slots__ = ('_ValueProperty__name')
+
+ def __init__(self):
+ self.__name = ""
+
+ @abstractmethod
+ def instance_restricted(self):
+ pass
+
+
+class PropertyInt(ValueProperty):
+ '''
+ Property class to store integer values
+
+ Contructor Parameters:
+ name: Name of the property of which integer value is to be stored
+ default: Current value of the property (Optional, default = 1)
+ minimum: Minimum value of the range of values that can be stored in the property object (Optional, default = 0)
+ maximum: Maximum value of the range of values that can be stored in the property object (Optional, default = 100)
+
+ '''
+ __slots__ = ('_ValueProperty__name', '_PropertyInt__default',
+ '_PropertyInt__minimum', '_PropertyInt__maximum')
+
+ def __init__(self, name: str, default: int = 1, minimum: int = 0, maximum: int = 100):
+ super(PropertyInt, self).__init__()
+ self.setProperties(name, default, minimum, maximum)
+
+ def instance_restricted(self):
+ pass
+
+ def setProperties(self, name: str, default: int, minimum: int, maximum: int):
+ '''
+ Function to edit the values stored in the object
+
+ Paramters:
+ name: Name of the property
+ default: Current value of the property
+ minimum: Minimum value of the range of values that can be stored in the property object
+ maximum: Maximum value of the range of values that can be stored in the property object
+
+ '''
+ if minimum > maximum:
+ raise InvalidRangeError()
+ elif default not in range(minimum, maximum+1):
+ raise DefaultOutofRangeError(default)
+ else:
+ self._ValueProperty__name = name
+ self.__default = default
+ self.__minimum = minimum
+ self.__maximum = maximum
+
+ def giveVal(self):
+ '''
+ Funciton to return the current value of the property
+ '''
+ res = self.__default
+ return res
+
+ def __repr__(self):
+ return f"PropertyInt(name = {self._ValueProperty__name}, default = {self.__default}, minimum = {self.__minimum}, maximum = {self.__maximum})"
+
+
+class PropertyFloat(ValueProperty):
+ '''
+ Property class to store float values
+
+ Contructor Parameters:
+ name: Name of the property of which float value is to be stored
+ default: Current value of the property (Optional, default = 1.0)
+ minimum: Minimum value of the range of values that can be stored in the property object (Optional, default = 0.0)
+ maximum: Maximum value of the range of values that can be stored in the property object (Optional, default = 100.0)
+
+ '''
+
+ __slots__ = ('_ValueProperty__name', '_PropertyFloat__default',
+ '_PropertyFloat__minimum', '_PropertyFloat__maximum')
+
+ def __init__(self, name=str, default: float = 1.0, minimum: float = 0.0, maximum: float = 100.0):
+ super(PropertyFloat, self).__init__()
+ self.setProperties(name, default, minimum, maximum)
+
+ def instance_restricted(self):
+ pass
+
+ def setProperties(self, name: str, default: float, minimum: float, maximum: float):
+ '''
+ Function to edit the values stored in the object
+
+ Paramters:
+ name: Name of the property
+ default: Current value of the property
+ minimum: Minimum value of the range of values that can be stored in the property object
+ maximum: Maximum value of the range of values that can be stored in the property object
+
+ '''
+ if minimum > maximum:
+ raise InvalidRangeError()
+ elif default > maximum or default < minimum:
+ raise DefaultOutofRangeError(default)
+ else:
+ self._ValueProperty__name = name
+ self.__default = default
+ self.__minimum = minimum
+ self.__maximum = maximum
+
+ def giveVal(self):
+ '''
+ Funciton to return the current value of the property
+ '''
+ res = self.__default
+ return res
+
+ def __repr__(self):
+ return f"PropertyFloat(name = {self._ValueProperty__name}, default = {self.__default}, minimum = {self.__minimum}, maximum = {self.__maximum})"
+
+
+class PropertyString(ValueProperty): # for testing purposes only, to be scrapped
+ '''
+ Property class to store string values
+
+ Contructor Parameters:
+ name: Name of the property of which string value is to be stored
+ default: Current value of the property (Optional, default = "")
+
+ '''
+ __slots__ = ('_ValueProperty__name', '_PropertyString__default')
+
+ def __init__(self, name: str, default: str = ""):
+ super(PropertyString, self).__init__()
+ self.setProperties(name, default)
+
+ def instance_restricted(self):
+ pass
+
+ def setProperties(self, name: str, default: str):
+ '''
+ Function to edit the values stored in the object
+
+ Paramters:
+ name: Name of the property
+ default: Current value of the property
+
+ '''
+ self._ValueProperty__name = name
+ self.__default = default
+
+ def giveVal(self):
+ '''
+ Funciton to return the current value of the property
+ '''
+ res = self.__default
+ return res
+
+ def __repr__(self):
+ return f"PropertyString(name = {self._ValueProperty__name}, default = '{self.__default}')"
+
+
+class EnumProp(ValueProperty):
+ '''
+ Property class to store values that are usually a choice out of many possible choices(string data)
+
+ Contructor Parameters:
+ name: Name of the property
+ items: set of all the possible choices
+ default: Current value of the property
+
+ '''
+
+ __slots__ = ('_EnumProp__items', '_EnumProp__default')
+
+ def __init__(self, name: str, items: {str}, default: str):
+ super(EnumProp, self).__init__()
+ self.setProperties(name, items, default)
+
+ def instance_restricted(self):
+ pass
+
+ def add_val(self, val: str) -> None:
+ '''
+ Function to add an option to the existing set of options
+
+ Parameters:
+ val: The new option that is to be added
+ '''
+ self.__items.add(val)
+
+ def get_items(self) -> {str}:
+ '''
+ Function to get the current set of choices available for the property
+
+ Returns:
+ items: set of current available options in the property
+ '''
+ return self.__items
+
+ def remove_item(self, val: str) -> None:
+ '''
+ Function to remove a choice from the set of choices in the property
+
+ Parameters:
+ val: The option that is to be removed
+ '''
+ if val != self.default:
+ self.__items.remove(val)
+ else:
+ raise IsDefaultError(val)
+
+ def set_default(self, val: str) -> None:
+ '''
+ Function to change the current value of the property
+
+ Parameters:
+ val: The new value of the property
+ '''
+ if val in self.items:
+ self.__default = val
+ else:
+ raise ValueOutofRangeError(val)
+
+ def setProperties(self, name: str, items: {str}, default: str):
+ '''
+ Function to edit the values stored in the object
+
+ Paramters:
+ name: Name of the property
+ items: set of all the possible choices
+ default: Current value of the property
+
+ '''
+ if type(items) != set:
+ raise NotSetType(items)
+ else:
+ for item in items:
+ if type(item) != str:
+ raise NotStringType(item)
+ else:
+ pass
+
+ if default not in items:
+ raise DefaultOutofRangeError(default)
+
+ self._ValueProperty__name = name
+ self.__items = items
+ self.__default = default
+
+ def __repr__(self):
+ return f"EnumProp(name = {self._ValueProperty__name}, items = {self.__items}, default = {self.__default})"
+
+ def giveVal(self):
+ '''
+ Funciton to return the current value of the property
+ '''
+ res = self.__default
+ return res \ No newline at end of file
diff --git a/pyvnt/Reference/errorClasses.py b/pyvnt/Reference/errorClasses.py
new file mode 100755
index 0000000..f1e3bda
--- /dev/null
+++ b/pyvnt/Reference/errorClasses.py
@@ -0,0 +1,65 @@
+'''
+This File stores the error classes that is used to display various errors that can be triggered while using this library
+'''
+
+
+class DefaultOutofRangeError(Exception):
+ def __init__(self, default: str):
+ self.default = default
+
+ def __str__(self):
+ return f"'{self.default}' not in property range"
+
+class LeafNodeError(Exception):
+ def __init__(self, default: str):
+ self.default = default
+
+ def __str__(self):
+ return f"{self.default} cannot have children nodes"
+
+class IsDefaultError(Exception):
+ def __init__(self, val: str):
+ self.val = val
+
+ def __str__(self):
+ return f"'{self.val}' is set as default value. Cannot remove {self.val}"
+
+
+class ValueOutofRangeError(Exception):
+ def __init__(self, val: str):
+ self.val = val
+
+ def __str__(self):
+ return f"'{self.val}' not in propery range"
+
+
+class KeyRepeatError(Exception):
+ def __init__(self, key: str):
+ self.key = key
+
+ def __str__(self):
+ return f"{self.key} Already exists"
+
+
+class NotStringType(TypeError):
+ def __init__(self, item):
+ self.item = item
+
+ def __str__(self):
+ return f"{self.item} not a string type"
+
+
+class NotSetType(TypeError):
+ def __init__(self, item):
+ self.item = item
+
+ def __str__(self):
+ return f"{self.item} not a set type"
+
+
+class InvalidRangeError(Exception):
+ def __init__(self):
+ pass
+
+ def __str__(self):
+ return f"Given range is invalid"
diff --git a/pyvnt/__init__.py b/pyvnt/__init__.py
new file mode 100755
index 0000000..f3073cd
--- /dev/null
+++ b/pyvnt/__init__.py
@@ -0,0 +1,4 @@
+from pyvnt.Reference.basic import *
+from pyvnt.DictionaryElement.foamDS import *
+from pyvnt.DictionaryElement.showTree import *
+from pyvnt.DictionaryElement.keyData import *
diff --git a/pyvnt/__pycache__/__init__.cpython-311.pyc b/pyvnt/__pycache__/__init__.cpython-311.pyc
new file mode 100644
index 0000000..d2350e4
--- /dev/null
+++ b/pyvnt/__pycache__/__init__.cpython-311.pyc
Binary files differ
diff --git a/pyvnt/test/treeTest.py b/pyvnt/test/treeTest.py
new file mode 100755
index 0000000..656dd7d
--- /dev/null
+++ b/pyvnt/test/treeTest.py
@@ -0,0 +1,11 @@
+from .pyvnt.DictionaryElement.foamDS import *
+from .pyvnt.DictionaryElement.keyData import *
+from .pyvnt.Reference.basic import *
+
+prop1 = EnumProp('val1', items={'PCG', 'PBiCG', 'PBiCGStab'}, default='PCG')
+
+key1 = KeyData('solver', prop1)
+
+head = Foam(name="test_head", children = [key1])
+
+head.dispTree() \ No newline at end of file
diff --git a/readme.md b/readme.md
deleted file mode 100644
index 8b13789..0000000
--- a/readme.md
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/setPackage.py b/setPackage.py
new file mode 100755
index 0000000..ef5cba6
--- /dev/null
+++ b/setPackage.py
@@ -0,0 +1,16 @@
+
+# Code to update the package in the testenv
+
+import os
+import shutil
+
+source = r"pyvnt"
+destination = r"../env/lib/python3.11/site-packages/pyvnt"
+target = r"../env/lib/python3.11/site-packages/pyvnt/"
+
+try:
+ shutil.rmtree(target)
+except:
+ pass
+
+shutil.copytree(source, destination) \ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100755
index 0000000..09b370d
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,33 @@
+from setuptools import setup, find_packages
+
+# this script for setting up the package for testing and using
+
+VERSION = '0.0.0'
+DESCRIPTION = 'Tree Data Structure for openFoam'
+
+# Setting up
+setup(
+ name="pyvnt",
+ version=VERSION,
+ author="",
+ author_email="<abs@gmail.com>",
+ description=DESCRIPTION,
+ packages_dir={"": "pyvnt"},
+ packages=find_packages(exclude=['test']),
+ install_requires=['anytree', 'dataclasses'],
+ keywords=['python'],
+ classifiers=[
+ "Development Status :: 1 - Planning",
+ "Intended Audience :: Developers",
+ "Programming Language :: Python :: 3",
+ "Operating System :: Unix",
+ "Operating System :: MacOS :: MacOS X",
+ "Operating System :: Microsoft :: Windows",
+ ]
+)
+
+# Command to run: python setup.py sdist bdist_wheel
+# this part is entirely optional, uncomment only if needed
+
+# import setPackage
+