44import json
55import os
66import re
7+ from pathlib import Path
78
89from Qt import QtCore , QtWidgets
910
@@ -775,14 +776,15 @@ def get_context_menu(self, menu):
775776 """
776777 return self ._context_menu .get (menu )
777778
778- def _deserialize_context_menu (self , menu , menu_data ):
779+ def _deserialize_context_menu (self , menu , menu_data , anchor_path = None ):
779780 """
780781 Populate context menu from a dictionary.
781782
782783 Args:
783784 menu (NodeGraphQt.NodeGraphMenu or NodeGraphQt.NodesMenu):
784785 parent context menu.
785786 menu_data (list[dict] or dict): serialized menu data.
787+ anchor_path (str or None): directory to interpret file paths relative to (optional)
786788 """
787789 if not menu :
788790 raise ValueError ('No context menu named: "{}"' .format (menu ))
@@ -792,6 +794,10 @@ def _deserialize_context_menu(self, menu, menu_data):
792794
793795 nodes_menu = self .get_context_menu ('nodes' )
794796
797+ anchor = Path (anchor_path ).resolve ()
798+ if anchor .is_file ():
799+ anchor = anchor .parent
800+
795801 def build_menu_command (menu , data ):
796802 """
797803 Create menu command from serialized data.
@@ -801,14 +807,16 @@ def build_menu_command(menu, data):
801807 menu object.
802808 data (dict): serialized menu command data.
803809 """
804- full_path = os .path .abspath (data ['file' ])
805- base_dir , file_name = os .path .split (full_path )
806- base_name = os .path .basename (base_dir )
807- file_name , _ = file_name .split ('.' )
810+ func_path = Path (data ['file' ])
811+ if not func_path .is_absolute ():
812+ func_path = anchor .joinpath (func_path )
813+
814+ base_name = func_path .parent .name
815+ file_name = func_path .stem
808816
809817 mod_name = '{}.{}' .format (base_name , file_name )
810818
811- spec = importlib .util .spec_from_file_location (mod_name , full_path )
819+ spec = importlib .util .spec_from_file_location (mod_name , func_path )
812820 mod = importlib .util .module_from_spec (spec )
813821 sys .modules [mod_name ] = mod
814822 spec .loader .exec_module (mod )
@@ -832,12 +840,12 @@ def build_menu_command(menu, data):
832840 elif item_type == 'menu' :
833841 sub_menu = menu .add_menu (menu_data ['label' ])
834842 items = menu_data .get ('items' , [])
835- self ._deserialize_context_menu (sub_menu , items )
843+ self ._deserialize_context_menu (sub_menu , items , anchor_path )
836844 elif isinstance (menu_data , list ):
837845 for item_data in menu_data :
838- self ._deserialize_context_menu (menu , item_data )
846+ self ._deserialize_context_menu (menu , item_data , anchor_path )
839847
840- def set_context_menu (self , menu_name , data ):
848+ def set_context_menu (self , menu_name , data , anchor_path = None ):
841849 """
842850 Populate a context menu from serialized data.
843851
@@ -875,11 +883,12 @@ def run_test(graph):
875883 Args:
876884 menu_name (str): name of the parent context menu to populate under.
877885 data (dict): serialized menu data.
886+ anchor_path (str or None): directory to interpret file paths relative to (optional)
878887 """
879888 context_menu = self .get_context_menu (menu_name )
880- self ._deserialize_context_menu (context_menu , data )
889+ self ._deserialize_context_menu (context_menu , data , anchor_path )
881890
882- def set_context_menu_from_file (self , file_path , menu = None ):
891+ def set_context_menu_from_file (self , file_path , menu = 'graph' ):
883892 """
884893 Populate a context menu from a serialized json file.
885894
@@ -892,16 +901,16 @@ def set_context_menu_from_file(self, file_path, menu=None):
892901 menu (str): name of the parent context menu to populate under.
893902 file_path (str): serialized menu commands json file.
894903 """
895- file_path = os . path . abspath (file_path )
904+ file = Path (file_path ). resolve ( )
896905
897906 menu = menu or 'graph'
898- if not os . path . isfile ( file_path ):
899- raise IOError ('file doesn\' t exists : "{}"' .format (file_path ))
907+ if not file . is_file ( ):
908+ raise IOError ('file doesn\' t exist : "{}"' .format (file ))
900909
901- with open (file_path ) as f :
910+ with file . open () as f :
902911 data = json .load (f )
903912 context_menu = self .get_context_menu (menu )
904- self ._deserialize_context_menu (context_menu , data )
913+ self ._deserialize_context_menu (context_menu , data , file )
905914
906915 def disable_context_menu (self , disabled = True , name = 'all' ):
907916 """
0 commit comments