funcnodes 0.2.2__tar.gz → 0.2.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. {funcnodes-0.2.2 → funcnodes-0.2.5}/PKG-INFO +6 -5
  2. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/__init__.py +1 -1
  3. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/basic_nodes/files.py +10 -1
  4. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/data.py +24 -4
  5. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/lib/libfinder.py +4 -1
  6. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/node.py +22 -2
  7. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/nodemaker.py +23 -1
  8. {funcnodes-0.2.2 → funcnodes-0.2.5}/pyproject.toml +11 -10
  9. {funcnodes-0.2.2 → funcnodes-0.2.5}/LICENSE +0 -0
  10. {funcnodes-0.2.2 → funcnodes-0.2.5}/README.md +0 -0
  11. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/__main__.py +0 -0
  12. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/_logging.py +0 -0
  13. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/basic_nodes/__init__.py +0 -0
  14. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/basic_nodes/logic.py +0 -0
  15. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/basic_nodes/math.py +0 -0
  16. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/config.py +0 -0
  17. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/eventmanager.py +0 -0
  18. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/exceptions.py +0 -0
  19. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/__init__.py +0 -0
  20. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/__init__.py +0 -0
  21. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/asset-manifest.json +0 -0
  22. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/css/style.css +0 -0
  23. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/favicon.ico +0 -0
  24. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/index.html +0 -0
  25. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/js/424.js +0 -0
  26. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/js/424.js.LICENSE.txt +0 -0
  27. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/js/main.js +0 -0
  28. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/js/main.js.LICENSE.txt +0 -0
  29. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/logo192.png +0 -0
  30. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/logo512.png +0 -0
  31. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/manifest.json +0 -0
  32. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/robots.txt +0 -0
  33. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/frontends/funcnodes_react/run.py +0 -0
  34. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/io.py +0 -0
  35. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/lib/__init__.py +0 -0
  36. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/lib/lib.py +0 -0
  37. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/lib/libparser.py +0 -0
  38. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/nodespace.py +0 -0
  39. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/triggerstack.py +0 -0
  40. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/utils/__init__.py +0 -0
  41. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/utils/data.py +0 -0
  42. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/utils/nodeutils.py +0 -0
  43. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/utils/serialization.py +0 -0
  44. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/worker/__init__.py +0 -0
  45. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/worker/external_worker.py +0 -0
  46. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/worker/loop.py +0 -0
  47. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/worker/remote_worker.py +0 -0
  48. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/worker/websocket.py +0 -0
  49. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/worker/worker.py +0 -0
  50. {funcnodes-0.2.2 → funcnodes-0.2.5}/funcnodes/worker/worker_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: funcnodes
3
- Version: 0.2.2
3
+ Version: 0.2.5
4
4
  Summary: funcnodes
5
5
  Author: Julian Kimmig
6
6
  Author-email: julian.kimmig@linkdlab.de
@@ -10,10 +10,11 @@ Classifier: Programming Language :: Python :: 3.9
10
10
  Classifier: Programming Language :: Python :: 3.10
11
11
  Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
- Requires-Dist: exposedfunctionality (>=0.3.6,<0.4.0)
14
- Requires-Dist: poetry-plugin-export (>=1.7.1,<2.0.0)
15
- Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
16
- Requires-Dist: virtualenv (>=20.25.1,<21.0.0)
13
+ Requires-Dist: exposedfunctionality (>=0.3,<0.4)
14
+ Requires-Dist: poetry
15
+ Requires-Dist: poetry-plugin-export (>=1.7,<2.0)
16
+ Requires-Dist: python-dotenv
17
+ Requires-Dist: virtualenv
17
18
  Requires-Dist: websockets (>=12.0,<13.0)
18
19
  Description-Content-Type: text/markdown
19
20
 
@@ -66,6 +66,6 @@ __all__ = [
66
66
  "DataEnum",
67
67
  ]
68
68
 
69
- __version__ = "0.2.2"
69
+ __version__ = "0.2.5"
70
70
 
71
71
  DEBUG = True
@@ -27,7 +27,16 @@ class FileDownloadNode(Node):
27
27
  url (str): The URL of the file to download.
28
28
  timeout (float): The timeout in seconds for the download request.
29
29
  """
30
- response = requests.get(url, timeout=timeout)
30
+ response = requests.get(
31
+ url,
32
+ timeout=timeout,
33
+ headers={
34
+ # set user agent to avoid 403 forbidden error
35
+ "User-Agent": "Mozilla/5.0",
36
+ # allow download of files
37
+ "Accept": "*/*",
38
+ },
39
+ )
31
40
  self.outputs["data"].value = response.content
32
41
 
33
42
 
@@ -33,14 +33,34 @@ class DataEnum(enum.Enum):
33
33
  cls.__name__,
34
34
  )
35
35
 
36
+ cls._lookup = {}
37
+ for member in cls:
38
+ cls._lookup[member.name] = member
39
+ try:
40
+ if member.value not in cls._lookup:
41
+ cls._lookup[member.value] = member
42
+ except TypeError:
43
+ pass
44
+ if str(member.value) not in cls._lookup:
45
+ cls._lookup[str(member.value)] = member
46
+
36
47
  @classmethod
37
48
  def interfere(cls: Type[ET], a: Union[ET, str, Any]) -> ET:
38
- if isinstance(a, str) and a in cls.__members__:
39
- return cls[a]
40
- elif isinstance(a, cls):
49
+
50
+ if isinstance(a, cls):
41
51
  return a
42
- else:
52
+ if a in cls._lookup:
53
+ return cls._lookup[a]
54
+ try:
43
55
  return cls(a)
56
+ except ValueError as e:
57
+ if isinstance(a, str):
58
+ if a.startswith(cls.__name__ + "."):
59
+ a = a[len(cls.__name__) + 1 :]
60
+ if a in cls._lookup:
61
+ return cls._lookup[a]
62
+
63
+ raise e
44
64
 
45
65
  @classmethod
46
66
  def v(cls: Type[ET], a: Union[ET, str, Any]) -> Any:
@@ -73,7 +73,10 @@ def find_shelf_from_module(
73
73
 
74
74
  module = importlib.import_module(strmod)
75
75
  # reload module to get the latest version
76
- importlib.reload(module)
76
+ try:
77
+ importlib.reload(module)
78
+ except Exception as e:
79
+ pass
77
80
  # for submod in submodules[1:]:
78
81
  # mod = getattr(mod, submod)
79
82
 
@@ -264,7 +264,7 @@ class Node(EventEmitterMixin, ABC, metaclass=NodeMeta):
264
264
 
265
265
  default_render_options: RenderOptions = {}
266
266
  default_io_options: Dict[str, NodeInputOptions | NodeOutputOptions] = {}
267
- default_trigger_on_create: bool = False
267
+ default_trigger_on_create: bool = True
268
268
 
269
269
  triggerinput = NodeInput(
270
270
  id="_triggerinput",
@@ -704,6 +704,7 @@ class Node(EventEmitterMixin, ABC, metaclass=NodeMeta):
704
704
  if "_triggerinput" in kwargs:
705
705
  del kwargs["_triggerinput"]
706
706
  try:
707
+
707
708
  ans = await self.func(**kwargs)
708
709
  # reset the inputs if requested
709
710
  if self.reset_inputs_on_trigger:
@@ -893,6 +894,23 @@ class FullNodeJSON(BaseNodeJSON):
893
894
  REGISTERED_NODES: Dict[str, Type[Node]] = {}
894
895
 
895
896
 
897
+ def _get_node_src(node: Type[Node]) -> str:
898
+ try:
899
+ file = inspect.getfile(node)
900
+ except Exception:
901
+ file = "<unknown file>"
902
+ try:
903
+ line = inspect.getsourcelines(node)[1]
904
+ except Exception:
905
+ line = "<unknown line>"
906
+
907
+ try:
908
+ module = node.__module__
909
+ except Exception:
910
+ module = "<unknown module>"
911
+ return f"{module}({file}:{line})"
912
+
913
+
896
914
  def register_node(node_class: Type[Node]):
897
915
  """
898
916
  Registers a node class by adding it to the REGISTERED_NODES dictionary with its 'node_id' as the key.
@@ -906,7 +924,9 @@ def register_node(node_class: Type[Node]):
906
924
  """
907
925
  node_id = node_class.node_id
908
926
  if node_id in REGISTERED_NODES:
909
- raise NodeIdAlreadyExistsError(f"Node with id {node_id} already exists")
927
+ raise NodeIdAlreadyExistsError(
928
+ f"Node with id '{node_id}' already exists at {_get_node_src(REGISTERED_NODES[node_id])}"
929
+ )
910
930
 
911
931
  REGISTERED_NODES[node_id] = node_class
912
932
 
@@ -37,6 +37,7 @@ def node_class_maker(
37
37
  id: Optional[str] = None,
38
38
  func: Callable[..., ReturnType] = None,
39
39
  superclass: Type[Node] = Node,
40
+ seperate_thread: bool = False,
40
41
  **kwargs: Unpack[NodeClassDict],
41
42
  ) -> Type[Node]:
42
43
  """
@@ -87,6 +88,22 @@ def node_class_maker(
87
88
  in_func: ExposedFunction[Coroutine[Any, Any, ReturnType]] = in_func
88
89
  asyncfunc = in_func
89
90
 
91
+ if seperate_thread:
92
+ oasyncfunc = asyncfunc
93
+
94
+ @wraps(oasyncfunc)
95
+ async def _wrapped_func(*args, **kwargs):
96
+ """
97
+ A wrapper for the exposed function that sets the output values of the node.
98
+ """
99
+ loop = asyncio.get_event_loop()
100
+ outs = await loop.run_in_executor(
101
+ None, lambda: asyncio.run(oasyncfunc(*args, **kwargs))
102
+ )
103
+ return outs
104
+
105
+ asyncfunc = _wrapped_func
106
+
90
107
  exfunc: ExposedFunction[Coroutine[Any, Any, ReturnType]] = asyncfunc
91
108
 
92
109
  @wraps(asyncfunc)
@@ -146,6 +163,7 @@ class NodeDecoratorKwargs(ExposedMethodKwargs, NodeClassDict, total=False):
146
163
  """
147
164
 
148
165
  superclass: Optional[Type[Node]]
166
+ seperate_thread: Optional[bool]
149
167
 
150
168
 
151
169
  def NodeDecorator(
@@ -176,7 +194,11 @@ def NodeDecorator(
176
194
  func = assure_exposed_method(func, **exposed_method_kwargs)
177
195
  # Create the node class
178
196
  return node_class_maker(
179
- id, func, superclass=kwargs.get("superclass", Node), **node_class_kwargs
197
+ id,
198
+ func,
199
+ superclass=kwargs.get("superclass", Node),
200
+ seperate_thread=kwargs.get("seperate_thread", False),
201
+ **node_class_kwargs,
180
202
  )
181
203
 
182
204
  return decorator
@@ -1,24 +1,25 @@
1
1
  [tool.poetry]
2
2
  name = "funcnodes"
3
- version = "0.2.2"
3
+ version = "0.2.5"
4
4
  description = "funcnodes"
5
5
  authors = ["Julian Kimmig <julian.kimmig@linkdlab.de>"]
6
6
  readme = "README.md"
7
7
 
8
8
  [tool.poetry.dependencies]
9
9
  python = "^3.9"
10
- exposedfunctionality = "^0.3.6"
10
+ exposedfunctionality = "^0.3"
11
11
  websockets = "^12.0"
12
- virtualenv = "^20.25.1"
13
- poetry-plugin-export = "^1.7.1"
14
- python-dotenv = "^1.0.1"
12
+ virtualenv = "*"
13
+ poetry-plugin-export = "^1.7"
14
+ python-dotenv = "*"
15
+ poetry = "*"
15
16
 
16
17
  [tool.poetry.group.dev.dependencies]
17
- pytest = "^7.4.2"
18
- coverage = "^7.3.2"
19
- pandas = "^2.2.0"
20
- pillow = "^10.2.0"
21
- opencv-python = "^4.9.0.80"
18
+ pytest = "^7.4"
19
+ coverage = "^7.3"
20
+ pandas = "^2.2"
21
+ pillow = "^10.2"
22
+ opencv-python = "^4.9"
22
23
  vulture = "^2.11"
23
24
 
24
25
  [build-system]
File without changes
File without changes
File without changes
File without changes