77import math
88import re
99
10- class CodeGenerator (QObject ):
10+ class CodeGenerator (QObject ):
1111 status_message_signal = pyqtSignal (str )
1212
13- def __init__ (self , django_root : str , app_folder : str , indent : int , pickled = False ):
13+ def __init__ (self , code_gen_widget , pickled = False ):
1414 super ().__init__ ()
15- self ._djangoRoot = django_root
16- self ._indentSpaces = indent
17- self ._appFolder = app_folder
15+
16+ self ._codeGenWidget = code_gen_widget
1817
1918 if not pickled :
2019 self ._djangoTree = {}
2120 self .finish_setup ()
2221
2322 def __setstate__ (self , data ):
24- self .__init__ (data ['django root' ], data [ 'app folder' ], data [ 'indent ' ], pickled = True )
23+ self .__init__ (data ['code gen widget ' ], pickled = True )
2524 self ._djangoTree = data ['django tree' ]
2625 self .finish_setup ()
2726
2827 def __getstate__ (self ):
2928 return {
3029 'django tree' : self ._djangoTree ,
31- 'django root' : self ._djangoRoot ,
32- 'indent' : self ._indentSpaces ,
33- 'app folder' : self ._appFolder ,
30+ 'django root' : self .code_generation_widget ,
31+ 'code gen widget' : self .code_generation_widget ,
3432 }
3533
3634 def finish_setup (self ):
3735 pass
3836
37+ @property
38+ def code_generation_widget (self ):
39+ return self ._codeGenWidget
40+
3941 @property
4042 def django_project_tree (self ):
4143 return self ._djangoTree
4244
4345 @property
4446 def django_project_root (self ):
45- return self ._djangoRoot
47+ return self .code_generation_widget . django_project_root
4648
4749 @property
4850 def num_indent_spaces (self ):
49- return self ._indentSpaces
51+ return self .code_generation_widget . indent_spaces_setting
5052
5153 @property
52- def app_folder (self ):
53- return self ._appFolder
54+ def input_file (self ):
55+ return self .code_generation_widget . input_file
5456
5557 def list_files_matching (self , path_pattern :str , recurse :bool = False ):
5658 files = glob (path_pattern , recurse )
5759 return files
58-
59- def output_view_code (self , function , name = None ):
60- module_path , module , attribs = self .get_module_attributes (self .django_project_root , self .app_folder , 'views.py' )
61-
62- if (name and name not in attribs ) or function .__name__ not in attribs :
63- if callable (function ):
64- source = inspect .getsource (function )
65- else :
66- source = str (function )
67-
68- source = f'\n { source } '
69-
70- with open (module_path , 'a' ) as module_file :
71- module_file .write (source )
72-
60+
7361 def load_module_with_path (self , module_path :str ):
7462 parts = os .path .normpath (module_path )
7563 parts = parts .split (os .sep )
7664 module_name = parts [- 1 ]
7765 module_name ,_ = os .path .splitext (module_name )
7866 module_spec = importlib .util .spec_from_file_location (module_name , location = module_path )
79- module = importlib .util .module_from_spec (module_spec )
67+ module = importlib .util .module_from_spec (module_spec )
68+ module_spec .loader .exec_module (module )
8069 return module
8170
8271 def tabify_code (self , code :str ):
@@ -110,33 +99,14 @@ def tabify_code(self, code:str):
11099
111100 return "\n " .join (tabified )
112101
113- def get_module_attributes (self , * args ):
114- module_path = os .path .join (* args )
115- module = self .load_module_with_path (module_path )
116- attribs = set (dir (module ))
117- return module_path , module , attribs
118-
119- def delete_view_code_if_unmodified (self , function ):
120- module_path , module , attribs = self .get_module_attributes (self .django_project_root , self .app_folder , 'views.py' )
121-
122- if callable (function ):
123- func_name = function .__name__
124- else :
125- func_name = str (function )
126-
127- if func_name in attribs :
128- existing = getattr (module , func_name )
129-
130- source = inspect .getsource (function )
131- existing_source = inspect .getsource (existing )
132-
133- if source == existing_source :
134- with open (module_path , 'rw' ) as module_file :
135- module_str = module_file .read ()
136- module_str = module_str .replace (source , '' )
137- module_file .write (module_str )
138- else :
139- self .status_message_signal .emit (f"{ func_name } code has been modified in { module_path } , so we won't delete it." )
102+ def module_attributes (self , * args ):
103+ try :
104+ module_path = os .path .join (* args )
105+ module = self .load_module_with_path (module_path )
106+ attribs = dir (module )
107+ return module_path , module , attribs
108+ except :
109+ return None , None , []
140110
141111 func_def_name_regex = re .compile (r"(?P<prefix>.*def\s+)(?P<name>[a-zA-Z_][a-zA-Z_0-9]*)(?P<suffix>\s*\(.*\)\s*:.*)" , flags = re .DOTALL )
142112 def function_def_renamed (self , code_str :str , new_name :str ):
@@ -147,19 +117,61 @@ def function_def_renamed(self, code_str:str, new_name:str):
147117 suffix = match .group ('suffix' )
148118 if name != new_name :
149119 return f'{ prefix } { new_name } { suffix } '
120+
121+ @property
122+ def export_mapper (self ):
123+ return self ._codeGenWidget .export_mapper
124+
125+ def app_folder (self , absolute = False ):
126+ django_file = self .export_mapper .django_output_file_mapping (self .input_file )
127+ django_file = self .export_mapper .filename_rel_root (django_file , root = self .export_mapper .django_project_root )
128+
129+ parts = django_file .split (os .sep )
130+
131+ if parts :
132+ if parts [0 ] == 'templates' :
133+ return self .django_settings_folder (absolute )
134+ else :
135+ if absolute == False :
136+ return parts [0 ]
137+ return os .path .join (self .export_mapper .django_project_root , parts [0 ])
150138
151- def rename_view_code (self , old_name :str , new_name :str ):
152- module_path , module , attribs = self .get_module_attributes (self .django_project_root , self .app_folder , 'views.py' )
153-
154- if old_name in attribs :
155- function = getattr (module , old_name )
156- old_source = inspect .getsource (function )
157- new_source = self .function_def_renamed (old_source , new_name )
139+ def django_settings_folder (self , absolute = False ):
140+ django_root = self .export_mapper .django_project_root
141+
142+ for folder in os .listdir (django_root ):
143+ filename = os .path .join (django_root , folder )
158144
159- with open (module_path , 'rw' ) as module_file :
160- string = module_file .read ()
161- string = string .replace (old_source , new_source )
162- module_file .write (string )
145+ if os .path .isdir (filename ):
146+ for file in os .listdir (filename ):
147+ if file == 'settings.py' :
148+ if absolute == False :
149+ return folder
150+ return filename
151+
152+ def jump_to_code_by_boilerplate (self , boiler_plate :str ):
153+ raise NotImplementedError
154+
155+ def _jump_to_code_by_boilerplate (self , boiler_plate :str ):
156+ raise NotImplementedError
157+
158+ def jump_to_code (self ):
159+ pass
160+
161+ @property
162+ def type_name (self ):
163+ return self .__class__ .__name__ [:- len ('Generator' )]
164+
165+ def get_boilerplate_attributes (self , base_file :str ):
166+ return self .module_attributes (self .django_project_root , self .export_mapper .bss_to_django_folder , self .export_mapper .boilerplates_folder , base_file )
167+
168+ @property
169+ def django_project_root (self ):
170+ return self .export_mapper .django_project_root
171+
172+ def list_boilerplates (self ):
173+ raise NotImplementedError
174+
163175
164176if __name__ == '__main__' :
165177 from PyQt5 .QtWidgets import QApplication
0 commit comments