class HistoryDemo(HasTraits): name = Str() file = File() directory = Directory() view = View( Item('name', id='name', editor=HistoryEditor(entries=5) ), Item('file', id='file1', editor=FileEditor(entries=10) ), Item('file', id='file2', editor=FileEditor(entries=10, filter=['All files (*.*)|*.*', 'Python files (*.py)|*.py']) ), Item('directory', id='directory', editor=DirectoryEditor(entries=10) ), title='History Editor Demo', id='enthought.test.history_demo.HistoryDemo', width=0.33, resizable=True )
def open_file_view(self): item = Item('file_name', id='file_tree', style='custom', show_label=False, width=0.5, editor=DirectoryEditor( filter=self.filter, allow_dir=True, reload_name='reload', dclick_name='dclick', )) width = height = 0.20 if len(self.extensions) > 0: raise Exception('extensions are not supported') return View(VGroup( VGroup(item), HGroup( Item('create', id='create', show_label=False, style='custom', defined_when='is_save_file', enabled_when='can_create_dir', tooltip='Create a new directory'), Item('file_name', id='history', editor=HistoryEditor(entries=self.entries, auto_set=True), springy=True), Item('ok', id='ok', show_label=False, enabled_when='is_valid_file'), Item('cancel', show_label=False))), title=self.title, id=self.id, kind='livemodal', width=width, height=height, close_result=False, resizable=True)
class LiveSearch(HasTraits): # The currenty root directory being searched: root = Directory(getcwd(), entries=10) # Should sub directories be included in the search: recursive = Bool(True) # The file types to include in the search: file_type = Enum('Python', 'C', 'C++', 'Java', 'Ruby') # The current search string: search = Str() # Is the search case sensitive? case_sensitive = Bool(False) # The live search table filter: filter = Property # Instance( TableFilter ) # The current list of source files being searched: source_files = Property # List( SourceFile ) # The currently selected source file: selected = Any # Instance( SourceFile ) # The contents of the currently selected source file: selected_contents = Property # List( Str ) # The currently selected match: selected_match = Int() # The text line corresponding to the selected match: selected_line = Property # Int # The full name of the currently selected source file: selected_full_name = Property # File # The list of marked lines for the currently selected file: mark_lines = Property # List( Int ) # Summary of current number of files and matches: summary = Property # Str #-- Traits UI Views ------------------------------------------------------ view = View( VGroup( HGroup( Item('root', id='root', label='Path', width=0.5 ), Item('recursive'), Item('file_type', label='Type'), Item('search', id='search', width=0.5, editor=HistoryEditor(auto_set=True) ), Item('case_sensitive') ), VSplit( VGroup( Item('summary', editor=TitleEditor() ), Item('source_files', id='source_files', editor=table_editor ), dock='horizontal', show_labels=False ), VGroup( HGroup( Item('selected_full_name', editor=TitleEditor(), springy=True ), Item('selected_full_name', editor=DNDEditor(), tooltip='Drag this file' ), show_labels=False ), Item('selected_contents', style='readonly', editor=CodeEditor(mark_lines='mark_lines', line='selected_line', selected_line='selected_line') ), dock='horizontal', show_labels=False ), id='splitter' ) ), title='Live File Search', id='enthought.examples.demo.Advanced.' 'Table_editor_with_live_search_and_cell_editor.LiveSearch', width=0.75, height=0.67, resizable=True ) #-- Property Implementations --------------------------------------------- @property_depends_on('search, case_sensitive') def _get_filter(self): if len(self.search) == 0: return lambda x: True return lambda x: len(x.matches) > 0 @property_depends_on('root, recursive, file_type') def _get_source_files(self): root = self.root if root == '': root = getcwd() file_types = FileTypes[self.file_type] if self.recursive: result = [] for dir_path, dir_names, file_names in walk(root): for file_name in file_names: if splitext(file_name)[1] in file_types: result.append(SourceFile( live_search=self, full_name=join(dir_path, file_name))) return result return [SourceFile(live_search=self, full_name=join(root, file_name)) for file_name in listdir(root) if splitext(file_name)[1] in file_types] @property_depends_on('selected') def _get_selected_contents(self): if self.selected is None: return '' return ''.join(self.selected.contents) @property_depends_on('selected') def _get_mark_lines(self): if self.selected is None: return [] return [int(match.split(':', 1)[0]) for match in self.selected.matches] @property_depends_on('selected, selected_match') def _get_selected_line(self): selected = self.selected if (selected is None) or (len(selected.matches) == 0): return 1 return int(selected.matches[self.selected_match - 1 ].split(':', 1)[0]) @property_depends_on('selected') def _get_selected_full_name(self): if self.selected is None: return '' return self.selected.full_name @property_depends_on('source_files, search, case_sensitive') def _get_summary(self): source_files = self.source_files search = self.search if search == '': return 'A total of %d files.' % len(source_files) files = 0 matches = 0 for source_file in source_files: n = len(source_file.matches) if n > 0: files += 1 matches += n return 'A total of %d files with %d files containing %d matches.' % ( len(source_files), files, matches) #-- Traits Event Handlers ------------------------------------------------ def _selected_changed(self): self.selected_match = 1 def _source_files_changed(self): if len(self.source_files) > 0: self.selected = self.source_files[0] else: self.selected = None
def open_file_view(self): """ Returns the file dialog view to use. """ # Set up the default file dialog view and size information: item = Item('file_name', id='file_tree', style='custom', show_label=False, width=0.5, editor=FileEditor(filter=self.filter, allow_dir=True, reload_name='reload', dclick_name='dclick')) width = height = 0.20 # Check to see if we have any extensions being added: if len(self.extensions) > 0: # fixme: We should use the actual values of the view's Width and # height traits here to adjust the overall width and height... width *= 2.0 # Assume we can used a fixed width Group: klass = HGroup # Set up to build a list of view Item objects: items = [] # Add each extension to the dialog: for i, extension in enumerate(self.extensions): # Save the extension in a new trait (for use by the View): name = 'extension_%d' % i setattr(self, name, extension) extension_view = extension # Sync up the 'file_name' trait with the extension: self.sync_trait('file_name', extension, mutual=True) # Check to see if it also defines the optional IFileDialogView # interface, and if not, use the default view information: if not extension.has_traits_interface(IFileDialogView): extension_view = default_view # Get the view that the extension wants to use: view = extension.trait_view(extension_view.view) # Determine if we should use a splitter for the dialog: if not extension_view.is_fixed: klass = HSplit # Add the extension as a new view item: items.append( Item(name, label=user_name_for(extension.__class__.__name__), show_label=False, style='custom', width=0.5, height=0.5, dock='horizontal', resizable=True, editor=InstanceEditor(view=view, id=name))) # Finally, combine the normal view element with the extensions: item = klass(item, VSplit(id='splitter2', springy=True, *items), id='splitter') # Return the resulting view: return View(VGroup( VGroup(item), HGroup( Item('create', id='create', show_label=False, style='custom', defined_when='is_save_file', enabled_when='can_create_dir', tooltip='Create a new directory'), Item('file_name', id='history', editor=HistoryEditor(entries=self.entries, auto_set=True), springy=True), Item('ok', id='ok', show_label=False, enabled_when='is_valid_file'), Item('cancel', show_label=False))), title=self.title, id=self.id, kind='livemodal', width=width, height=height, close_result=False, resizable=True)
class HB_HeapBrowser ( HasPrivateTraits ): # The name of the plugin: name = Str( 'Heap Browser' ) # The current heap statistics table entries: current_counts = List( HB_ClassCount ) # The list of currently selected counts: selected_counts = List( HB_ClassCount ) # The sting that all class names must contain: filter_name = Str( event = 'heap_updated' ) # The threshold for the number of instances to display: filter_instances = Int( event = 'heap_updated' ) # The threshold for the amount of change to display: filter_change = Int( event = 'heap_updated' ) # Number of items in the current_counts list: current_classes = Property( depends_on = 'current_counts' ) # Total number of instances in the current_counts list: current_instances = Property( depends_on = 'current_counts' ) # Total change in the current_counts list: current_change = Property( depends_on = 'current_counts' ) # Indicates whether or not the selection set is empty or not: has_counts = Property # The set of all current active object ids: current_ids = Any( set() ) # Current heap statistics: current_heap = Any( {} ) # Previous heap statistics: previous_heap = Any( {} ) # Event fired when anything changes that affects the heap statistics view: heap_updated = Event # The list of object classes currently being ignored: ignored_classes = Any( set() ) # The list of object classes currently being shown: shown_classes = Any( set() ) # Refresh button: refresh = Button( 'Refresh' ) # Baseline button (to create a new 'baseline' set): baseline = Button( 'Baseline' ) # Hide all selected items button: hide_selected = Button( 'Hide Selected' ) # Show only the selected items button: show_selected = Button( 'Show Selected' ) # Show all items button: show_all = Button( 'Show All' ) # Show the details of the current selected items button: show_details = Button( 'Show Details' ) # Event fired when a 'counts' item is double-clicked: counts_dclick = Event #-- View 2 Traits ---------------------------------------------------------- # The list of objects which the user has requested detailed information for: details = List( HB_Detail ) #-- View 3 Traits ---------------------------------------------------------- # The list of object referrer trees: referrers = List( HB_Referrers ) #-- View 4 Traits ---------------------------------------------------------- # The list of object baselines: baselines = List( HB_Baseline ) #-- Traits View Definitions ------------------------------------------------ heap_stats_view = View( VSplit( VGroup( HGroup( Item( 'filter_name', id = 'filter_name', label = 'Name', width = -90, editor = HistoryEditor( auto_set = True ), ), '_', Item( 'filter_instances', label = 'Min Instances', width = -36 ), '_', Item( 'filter_change', label = 'Min Change', width = -36 ), '_', spring, '_', Item( 'current_classes', label = 'Classes', style = 'readonly', format_func = commatize, width = -35 ), '_', Item( 'current_instances', label = 'Instances', style = 'readonly', format_func = commatize, width = -50 ), '_', Item( 'current_change', label = 'Change', style = 'readonly', format_func = commatize, width = -50 ), ), Item( 'current_counts', id = 'current_counts', editor = counts_table_editor ), '_', HGroup( Item( 'refresh', tooltip = 'Refresh the heap statistics' ), Item( 'baseline', tooltip = 'Create a new baseline set' ), spring, Item( 'hide_selected', tooltip = 'Remove all selected items from the view', enabled_when = 'has_counts' ), Item( 'show_selected', tooltip = 'Show only the selected items in the view', enabled_when = 'has_counts' ), Item( 'show_all', tooltip = 'Show all items again', enabled_when = '(len( ignored_classes ) > 0) ' 'or (len( shown_classes ) > 0)' ), '_', Item( 'show_details', tooltip = 'Show the instances of the selected ' 'classes', enabled_when = 'has_counts' ), show_labels = False, ), label = 'Heap', show_labels = False, dock = 'tab' ), Item( 'details', id = 'details', style = 'custom', dock = 'tab', editor = ListEditor( use_notebook = True, deletable = True, dock_style = 'tab', export = 'DockWindowShell', page_name = '.short_name' ) ), Item( 'referrers', id = 'referrers', style = 'custom', dock = 'tab', editor = ListEditor( use_notebook = True, deletable = True, dock_style = 'tab', export = 'DockWindowShell', page_name = '.name' ) ), Item( 'baselines', id = 'baselines', style = 'custom', dock = 'tab', editor = ListEditor( use_notebook = True, deletable = True, dock_style = 'tab', export = 'DockWindowShell', page_name = 'Baseline' ) ), id = 'splitter', show_labels = False ), title = 'Heap Browser', id = 'etsdevtools.developer.tools.heap_browser.HB_HeapBrowser', width = 0.5, height = 0.75, resizable = True, key_bindings = heap_browser_key_bindings ) #-- Property Implementations ----------------------------------------------- def _get_has_counts ( self ): return (len( self.selected_counts ) > 0) def _get_current_classes ( self ): return len( self.current_counts ) @cached_property def _get_current_instances ( self ): return reduce( lambda l, r: l + r.instances, self.current_counts, 0 ) @cached_property def _get_current_change ( self ): return reduce( lambda l, r: l + r.change, self.current_counts, 0 ) #-- Event Handlers --------------------------------------------------------- def _heap_updated_changed ( self ): """ Handles the 'heap_updated' event being fired by rebuilding the heap class counts list. """ ignored = ignored_classes shown = self.shown_classes no_show = (len( shown ) == 0) if no_show: ignored = ignored_classes.union( self.ignored_classes ) old = self.previous_heap filter_name = self.filter_name.lower() filter_instances = self.filter_instances filter_change = self.filter_change counts = [ HB_ClassCount( name = name, instances = instances, change = instances - old.get( name, 0 ) ) for name, instances in self.current_heap.iteritems() if (name not in ignored) and (no_show or (name in shown)) and (name.lower().find( filter_name ) >= 0) and (instances >= filter_instances) and (abs( instances - old.get( name, 0 ) ) >= filter_change) ] counts.sort( lambda l, r: cmp( l.lower_name, r.lower_name ) ) self.current_counts = counts def _refresh_changed ( self, ignore = None ): """ Handles the 'Refresh' button being clicked. """ self.update() def _baseline_changed ( self, ignore = None ): """ Handles the 'Baseline' button being clicked. """ self.baselines.append( self._create_baseline() ) def _hide_selected_changed ( self, info = None ): """ Handles the 'Hide Selected' button being clicked. """ self.ignored_classes.update( set( [ item.name for item in self.selected_counts ] ) ) self.shown_classes.clear() del self.selected_counts[:] self.heap_updated = True def _show_selected_changed ( self, info = None ): """ Handles the 'Show Selected' button being clicked. """ self.shown_classes = set( set( [ item.name for item in self.selected_counts ] ) ) self.ignored_classes.clear() del self.selected_counts[:] self.heap_updated = True def _show_all_changed ( self, info = None ): """ Handles the 'Show All' button being clicked. """ self.ignored_classes.clear() self.shown_classes.clear() del self.selected_counts[:] self.heap_updated = True def _show_details_changed ( self, ignore = True ): """ Handles the 'Show Details' button being clicked. """ self.details.extend( [ HB_Detail( name = item.name, owner = self ) for item in self.selected_counts ] ) def _counts_dclick_changed ( self, event ): """ Handles the user double-clicking a 'counts' table entry in order to show its details. """ item, column = event self.details.append( HB_Detail( name = item.name, owner = self ) ) def _set_filter_change_1 ( self, info = None ): """ Sets the filter change value to 1. """ self.filter_change = 1 def _clear_filter ( self, info = None ): """ Clears all current filter variable settings back to their defaults. """ self.filter_change = filter_instances = 0 self.filter_name = '' def _select_all ( self, info = None ): """ Selects all current displayed items. """ self.selected_counts = self.current_counts def _unselect_all ( self, info = None ): """ Unselects all currently selected items. """ self.selected_counts = [] #-- Public Methods --------------------------------------------------------- def update ( self ): """ Updates the heap statistics. """ self.previous_heap = old = self.current_heap self.current_heap = new = {} self.current_ids = ids = set() gc.collect() for object in gc.get_objects(): name = object_name( object ) if name not in ignored_classes: new[ name ] = new.setdefault( name, 0 ) + 1 ids.add( id( object ) ) self.heap_updated = True # Indicate that each class detail should update its instance # information: for detail in self.details: detail.update = True # Indicate that each referrer should update its instance information: for referrer in self.referrers: referrer.root.update = True # Indicate that each baseline view should update its contents: for baseline in self.baselines: baseline.update = ids #-- Private Methods -------------------------------------------------------- def _create_baseline ( self ): """ Creates a new baseline object. """ current_ids = self.current_ids object_ids = {} gc.collect() for object in gc.get_objects(): if id( object ) not in current_ids: name = object_name( object ) if name not in ignored_classes: object_ids[ id( object ) ] = name return HB_Baseline( object_ids = object_ids, owner = self )