根目录
	robotide

	1、入口函数
		__init__.py:
		
			def main(*args):
				noupdatecheck, debug_console, inpath = _parse_args(args)  # 命令解析  返回参数 noupdatecheck, debug_console, inpath  都传入Ride
				
			def _parse_args(args):
					noupdatecheck = '--noupdatecheck' in args
					debug_console = '--debugconsole' in args
					
				_run(inpath, not noupdatecheck, debug_console)   入口函数
				
			def _run(inpath=None, updatecheck=True, debug_console=False): 
				# print(f"DEBUG: ENTER _run {inpath=}, {updatecheck=}, {debug_console=}")
				try:
					from robotide.application import RIDE # 主界面
					from robotide.application import debugconsole   # 调试后台
				except ImportError:
					_show_old_wxpython_warning_if_needed()
					raise
				ride = RIDE(inpath, updatecheck)   #  初始化
				if wx.VERSION <= (4, 0, 4, '', ''):
					_show_old_wxpython_warning_if_needed(ride.frame)
				else:
					wx.CallAfter(_show_old_wxpython_warning_if_needed, ride.frame)
				if debug_console:
					wx.lib.inspection.InspectionTool().Show()
					debugconsole.start(ride)   # 启动debugconsole
				ride.MainLoop()  # 消息循环
		
	robotide\application\application.py
		class RIDE(wx.App):
			    def OnInit(self):  # Overrides wx method
					# DEBUG To test RTL
					# self._initial_locale = wx.Locale(wx.LANGUAGE_ARABIC)
					self._initial_locale = wx.Locale(wx.LANGUAGE_ENGLISH_US)
					# Needed for SetToolTipString to work
					wx.HelpProvider.Set(wx.SimpleHelpProvider())  # DEBUG: adjust to wx versions
					# 配置读取
					self.settings = RideSettings()
					# 数据库初始化
					librarydatabase.initialize_database()
					# 配置
					self.preferences = Preferences(self.settings)
					# 初始化
					self.namespace = Namespace(self.settings)
					# 构建项目控制器
					self._controller = Project(self.namespace, self.settings)
					# 构建RideFrame
					self.frame = RideFrame(self, self._controller)
					# DEBUG  self.frame.Show()
					self._editor_provider = EditorProvider()
					self._plugin_loader = PluginLoader(self, self._get_plugin_dirs(),
													   coreplugins.get_core_plugins())
					self._plugin_loader.enable_plugins()
					perspective = self.settings.get('AUI Perspective', None)
					if perspective:
						self.frame.aui_mgr.LoadPerspective(perspective, True)
					try:
						nb_perspective = self.settings.get('AUI NB Perspective', None)
						if nb_perspective:
							self.frame.notebook.LoadPerspective(nb_perspective)
					except Exception as e:
						print(f"RIDE: There was a problem loading panels position."
							  f" Please delete the definition 'AUI NB Perspective' in "
							  f"{os.path.join(context.SETTINGS_DIRECTORY, 'settings.cfg')}")
						if not isinstance(e, IndexError):  # If is with all notebooks disabled, continue
							raise e
					self.treeplugin = TreePlugin(self)
					if self.treeplugin.settings['_enabled']:
						self.treeplugin.register_frame(self.frame)
					self.fileexplorerplugin = FileExplorerPlugin(self, self._controller)
					if self.fileexplorerplugin.settings['_enabled']:
						self.fileexplorerplugin.register_frame(self.frame)
					if not self.treeplugin.opened:
						self.treeplugin.close_tree()
					# else:
					#     wx.CallLater(200, self.treeplugin.populate, self.model)
					if not self.fileexplorerplugin.opened:
						self.fileexplorerplugin.close_tree()
					self.editor = self._get_editor()
					self.robot_version = self._find_robot_installation()
					# 加载数据-------
					self._load_data()
					self.treeplugin.populate(self.model)
					self.treeplugin.set_editor(self.editor)
					self._publish_system_info()
					self.frame.Show()    # ###### DEBUG DANGER ZONE
					self.SetTopWindow(self.frame)
					self.frame.aui_mgr.Update()
					wx.CallLater(200, ReleaseNotes(self).bring_to_front)
					wx.CallLater(200, self.fileexplorerplugin.update_tree)
					if self._updatecheck:
						wx.CallAfter(UpdateNotifierController(self.settings).notify_update_if_needed, UpdateDialog)
					self.Bind(wx.EVT_ACTIVATE_APP, self.on_app_activate)
					PUBLISHER.subscribe(self.SetGlobalColour, RideSettingsChanged)
					PUBLISHER.subscribe(self.update_excludes, RideSettingsChanged)
					RideSettingsChanged(keys=('Excludes', 'init'), old=None, new=None).publish()
					return True
					
			class Namespace(object):		
			   def _init_caches(self):
				# 库
				self._lib_cache = LibraryCache(
					self.settings, self.update, self._library_manager)
				# 资源
				self._resource_factory = ResourceFactory(self.settings)
				# 数据文件 数据文件检索器
				self._retriever = DatafileRetriever(self._lib_cache,
													self._resource_factory, self)
				self._context_factory = _RetrieverContextFactory()
				
			class LibraryCache(object):
				def __init__(self, settings, libraries_need_refresh_listener,
							 library_manager):
					self._library_manager = None
					self._settings = settings
					if library_manager:
						self.set_library_manager(library_manager)  #设置_library_manager
					self._libraries_need_refresh_listener = libraries_need_refresh_listener
					self._library_keywords = {}
					self.__default_libraries = None
					self.__default_kws = None
		
			class ResourceFactory(object):
				_IGNORE_RESOURCE_DIRECTORY_SETTING_NAME = 'ignored resource directory'

				def __init__(self, settings):
					self.cache = {}
					self.python_path_cache = {}
					self._excludes = settings.excludes
					self.check_path_from_excludes = self._excludes.contains  
					# print("DEBUG: ResourceFactory init path_excludes %s\n" % self.check_path_from_excludes)
			
			class DatafileRetriever(object):
				def __init__(self, lib_cache, resource_factory, namespace):
					self._namespace = namespace
					self._lib_cache = lib_cache
					self._resource_factory = resource_factory
					# 关键字缓存
					self.keyword_cache = ExpiringCache()  #过期缓存
					self._default_kws = None
			
			class Project(_BaseController, WithNamespace):
				def __init__(self, namespace=None, settings=None, library_manager=None):
					from .filecontrollers import ResourceFileControllerFactory
					self._library_manager = self._construct_library_manager(library_manager, settings)  # 静态方法 构建库管理器
					if not self._library_manager.is_alive():
						self._library_manager.start()  # 开启_library_manager
					self._name_space = namespace
					self._set_namespace(self._name_space)
					self.internal_settings = settings
					self._loader = DataLoader(self._name_space, settings)  # 数据加载器
					self.controller = None
					self.name = None
					self.external_resources = []
					self._resource_file_controller_factory = ResourceFileControllerFactory(self._name_space, self)   # 构建资源文件控制器工厂
					self._serializer = Serializer(settings, LOG)  # 序列化
		
				@staticmethod
				def _construct_library_manager(library_manager, settings):
					# 'C:\\Users\\Administrator\\AppData\\Roaming\\RobotFramework\\ride\\librarykeywords.db'
					return library_manager or \
						spec.LibraryManager(spec.DATABASE_FILE, SpecInitializer(settings.get('library xml directories', [])[:]))   # 环境库地址
						
						
			class LibraryManager(Thread):  # 守护多线程
				def __init__(self, database_name, spec_initializer=None):
					self._database_name = database_name
					self._database = None
					self._messages = queue.Queue()  # 消息队列
					self._spec_initializer = spec_initializer or SpecInitializer()
					Thread.__init__(self)
					self.daemon = True
						
				def run(self):
					self._initiate_database_connection()
					while True:
						try:
							if not self._handle_message():
								break
						except Exception as err:
							msg = 'Library import handling threw an unexpected exception'
							RideLogException(message=msg, exception=err, level='WARN').publish()
					self._database.close()
						
				def _handle_message(self):
					# 库消息处理
					message = self._messages.get()
					if not message:
						return False
					msg_type = message[0]
					if msg_type == 'fetch': # fetch
						self._handle_fetch_keywords_message(message)
					elif msg_type == 'insert': # insert
						self._handle_insert_keywords_message(message)
					elif msg_type == 'create': # create_database
						self._database.create_database()
					return True
					
				def _handle_insert_keywords_message(self, message):
					_, library_name, library_args, result_queue = message  # message????何时传入
					keywords = self._fetch_keywords(library_name, library_args)
					self._insert(library_name, library_args, keywords,
								 lambda res: result_queue.put(res, timeout=3))	
				
				def _insert(self, library_name, library_args, keywords, callback):
					self._database.insert_library_keywords(   # LibraryDatabase::insert_library_keywords
						library_name, library_args, keywords or [])
					self._call(callback, keywords)
				
			class DataLoader(object):

				def __init__(self, namespace, settings):
					self.namespace = namespace
					self.namespace.reset_resource_and_library_cache()   # namespace 重置资源库缓存
					self._settings = settings	  
					
					Namespace::def reset_resource_and_library_cache(self):
						self._init_caches()	
						
			class ResourceFileControllerFactory(object):

				def __init__(self, namespace, project):
					self._resources = []
					self._namespace = namespace
					self._project = project
					self._all_resource_imports_resolved = False
		
			class Serializer(object):

				def __init__(self, settings, logger):
					self._settings = settings
					self._logger = logger
					self._errors = []
						
								
					
					
	class RideFrame(wx.Frame):

		def __init__(self, application, controller):
			size = application.settings.get('mainframe size', (1100, 700))
			# DEBUG self.general_settings = application.settings['General']
			wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title='RIDE',
							  pos=application.settings.get(MAINFRAME_POSITION, (50, 30)),
							  size=size, style=wx.DEFAULT_FRAME_STYLE | wx.SUNKEN_BORDER | wx.BORDER_THEME)

			# set Left to Right direction (while we don't have localization)
			self.SetLayoutDirection(wx.Layout_LeftToRight)
			# self.SetLayoutDirection(wx.Layout_RightToLeft)

			self.aui_mgr = aui.AuiManager(self)

			# tell AuiManager to manage this frame
			self.aui_mgr.SetManagedWindow(self)

			self.SetMinSize(wx.Size(400, 300))

			self.ensure_on_screen()
			if application.settings.get(MAINFRAME_MAXIMIZED, False):
				self.Maximize()
			self._application = application
			self.controller = controller
			self._image_provider = ImageProvider()
			self.reformat = application.settings.get('reformat', False)
			self.general_settings = application.settings['General']  # .get_without_default('General')
			self.color_background_help = self.general_settings.get('background help', (240, 242, 80))
			self.color_foreground_text = self.general_settings.get('foreground text', (7, 0, 70))
			self.color_background = self.general_settings.get_without_default('background')
			self.color_foreground = self.general_settings.get_without_default('foreground')
			self.font_face = self.general_settings.get('font face', '')
			self.font_size = self.general_settings.get('font size', 11)
			self._init_ui()
			self._task_bar_icon = RIDETaskBarIcon(self, self._image_provider)
			self._plugin_manager = PluginManager(self.notebook)
			self._review_dialog = None
			self._view_all_tags_dialog = None
			self._current_external_dir = None
			self.Bind(wx.EVT_CLOSE, self.on_close)
			self.Bind(wx.EVT_SIZE, self.on_size)
			self.Bind(wx.EVT_MOVE, self.on_move)
			self.Bind(wx.EVT_MAXIMIZE, self.on_maximize)
			self.Bind(wx.EVT_DIRCTRL_FILEACTIVATED, self.on_open_file)
			self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.on_menu_open_file)
			self._subscribe_messages()
			wx.CallAfter(self.actions.register_tools)  # DEBUG
			# DEBUG wx.CallAfter(self.OnSettingsChanged, self.general_settings)	
					
					
					
		RIDE::def _load_data(self):
			self.workspace_path = self.workspace_path or self._get_latest_path()
			if self.workspace_path:
				# 更新当前默认项目地址
				self._controller.update_default_dir(self.workspace_path)
				# 加载进度服务
				observer = LoadProgressObserver(self.frame)
				
				self._controller.load_data(self.workspace_path, observer)			
					
					
				-->Project::def load_data(self, path, load_observer=None):
					""" DEBUG: To be used in Localization
					from robotide.context import APP
					try:
						robot_version = APP.robot_version
					except AttributeError:
						robot_version = b'6.1.1'  # It is failing at unit tests
					print(f"DEBUG: project.py Project ENTER robot version = {robot_version}")
					"""
					load_observer = load_observer or NullObserver()
					if self._load_initfile(path, load_observer):
						return
					if self._load_datafile(path, load_observer):
						return
					if self._load_resource(path, load_observer):
						return
					try:
						load_observer.error("Given file '%s' is not a valid Robot Framework "
											"test case or resource file." % path)
					except AttributeError:  # DEBUG
						# print(f"DEBUG: load_data error not valid datafile: {path}")
						pass
					-->_load_initfile
						    def _load_initfile(self, path, load_observer):
								if os.path.splitext(os.path.split(path)[1])[0] != '__init__':
									return None
								initfile = self._loader.load_initfile(path, load_observer)
								if not initfile:
									return None
								self._populate_from_datafile(path, initfile, load_observer)
								return initfile
					-->_load_datafile
					-->_load_resource
					
					
					
		OnInit--》
			1、self.settings = RideSettings() 
			2、librarydatabase.initialize_database()
			3、self.preferences = Preferences(self.settings)		
			4、self.namespace = Namespace(self.settings)	--》
					 self._init_caches() # 缓存初始化--》
						self._lib_cache = LibraryCache(self.settings, self.update, self._library_manager)--》
							self._libraries_need_refresh_listener = libraries_need_refresh_listener==update
							self._library_keywords = {}
							self.__default_libraries = None
							self.__default_kws = None
						# 资源
						self._resource_factory = ResourceFactory(self.settings)--》
							self._excludes = settings.excludes
							self.check_path_from_excludes = self._excludes.contains
						# 数据文件 数据文件检索器
						self._retriever = DatafileRetriever(self._lib_cache,self._resource_factory, self)--》
							self._namespace = namespace
							self._lib_cache = lib_cache
							self._resource_factory = resource_factory
							self.keyword_cache = ExpiringCache()
							self._default_kws = None
						self._context_factory = _RetrieverContextFactory()
						
					 self._set_pythonpath()
					 PUBLISHER.subscribe(self._setting_changed, RideSettingsChanged)
					 
			5、self._controller = Project(self.namespace, self.settings)	--》	
				1、开启_library_manager线程
				self._library_manager = self._construct_library_manager(library_manager, settings)
				if not self._library_manager.is_alive():
					self._library_manager.start()
				2、self._set_namespace(self._name_space)
					namespace.set_library_manager(self._library_manager)--》	
						def set_library_manager(self, library_manager):
							self._library_manager = library_manager
							self._lib_cache.set_library_manager(library_manager)--》	
								self._library_manager = library_manager
					WithNamespace._set_namespace(self, namespace)
						 
				3、self._loader = DataLoader(self._name_space, settings)  # 数据加载器
					   self.namespace.reset_resource_and_library_cache()
							self._init_caches()
								self._lib_cache = LibraryCache(self.settings, self.update, self._library_manager)
								# 资源
								self._resource_factory = ResourceFactory(self.settings)
								# 数据文件 数据文件检索器
								self._retriever = DatafileRetriever(self._lib_cache,self._resource_factory, self)
								self._context_factory = _RetrieverContextFactory()
				4、self._resource_file_controller_factory = ResourceFileControllerFactory(self._name_space, self)
						self._resources = []
						self._namespace = namespace
						self._project = project
						self._all_resource_imports_resolved = False		
				5、self._serializer = Serializer(settings, LOG)				
						self._settings = settings
						self._logger = logger
						self._errors = []
			 # 创建 RideFrame
			6、self.frame = RideFrame(self, self._controller)
				self.controller = controller
				self._subscribe_messages()
					
						

 

posted on 2024-10-09 13:49  Old-Kang  阅读(4)  评论(0编辑  收藏  举报