def get_display(self): self.order_sk = str(self.kwargs.get("order_sk")) self.title_code = str(self.kwargs.get("title_code")) full_title = str(self.kwargs.get("full_title")) delivs_search = Search("twog/work_order_deliverables") delivs_search.add_filter("title_code", self.title_code) delivs = delivs_search.get_sobjects() linked = [] for d in delivs: linked.append(d.get_value("satisfied")) satisfied = 0 unsatisfied = 0 for link in linked: if link == True: satisfied += 1 else: unsatisfied += 1 table = Table() table.add_row() deliverable_launcher = table.add_cell("<u>Delivs: (%s/%s)</u>" % (satisfied, satisfied + unsatisfied)) deliverable_launcher.add_attr("nowrap", "nowrap") deliverable_launcher.add_attr("valign", "bottom") deliverable_launcher.add_style("font-size: 80%;") deliverable_launcher.add_style("font-color: #2e2e2e;") deliverable_launcher.add_style("cursor: pointer;") deliverable_launcher.add_behavior(get_launch_deliverables_behavior(self.order_sk, self.title_code, full_title)) return table
def execute(self): web = WebContainer.get_web() if web.get_form_value("update") != "true": return self.element_name = self.kwargs.get("element_name") security_groups = web.get_form_values("security") from pyasm.security import AccessRuleBuilder, AccessManager rule_group = "side_bar" for security_group in security_groups: if not security_group: continue search = Search("sthpw/login_group") search.add_filter("login_group", security_group) login_group = search.get_sobject() assert login_group access_rules = login_group.get_xml_value("access_rules") # add the rule to each group builder = AccessRuleBuilder(access_rules) builder.add_rule(rule_group, self.element_name, "deny") login_group.set_value("access_rules", builder.to_string()) login_group.commit()
def get_notes_wdg(my): widget = Widget() div = DivWdg(css='filter_box') asset_filter = AssetFilterWdg() div.add(asset_filter) search_limit = SearchLimitWdg() div.add(search_limit) context_select = FilterSelectWdg("discussion_context") context_select.set_option("setting", "notes_prod_context") context_select.add_empty_option("<- Any Context ->") span = SpanWdg(css="med") span.add("Notes Context: ") span.add(context_select) div.add(span) widget.add(div) # create a search search = Search("prod/asset") asset_filter.alter_search(search) sobjects = search.get_sobjects() table = TableWdg("prod/asset", "prod_notes") table.set_class("table") table.set_sobjects(sobjects) widget.add(table) return widget
def get_display(self): sobject = self.get_current_sobject() sobject = sobject.get_parent() if not sobject: return Widget() # get all of the sobject_logs search = Search("sthpw/sobject_log") search.add_sobject_filter(sobject) logs = search.get_sobjects() search = Search("sthpw/transaction_log") search.add_filters("id", [x.get_value("transaction_log_id") for x in logs] ) search.set_limit(200) logs = search.get_sobjects() from layout_wdg import TableWdg widget = Widget() table = TableWdg("sthpw/transaction_log") table.add_class("minimal") table.set_header_flag(False) table.set_show_property(False) table.set_no_results_wdg( " " ) table.set_sobjects(logs) widget.add(table) return widget
def fix_day(my, verbose=False): search = Search('sthpw/work_hour') sobjects = search.get_sobjects() if verbose: print "Searching %s" % search_type print " ... found %s sobjects" % len(sobjects) for i, sobject in enumerate(sobjects): # change back to pst for day that has finite hours day = sobject.get_value("day") try: if not day.endswith('00:00:00'): date, hrs = day.split(' ') new_day = '%s 00:00:00'%date print "code: %s [%s]" %(sobject.get_code(), day) date = parser.parse(new_day) date = date + relativedelta(days=1) print "adjusted day ", date sobject.set_value("day", str(date)) sobject.commit(triggers=False) my.count += 1 except Exception, e: if verbose: print "ERROR: ", e, " for sobject: ", sobject.get_search_type(), sobject.get_code()
def get_display(self): outer_div = DivWdg() outer_div.set_id('add_deliverable_files_to_package') order_code = self.package_sobject.get('order_code') order_search = Search('twog/order') order_search.add_code_filter(order_code) order_sobject = order_search.get_sobject() deliverable_files = get_deliverable_files_in_order(order_sobject) selected_files = get_files_for_package(self.package_sobject.get_code()) # Only show the selectable files and the submit button if the parent order has any deliverable files if deliverable_files: deliverable_file_select_wdg = get_files_checkbox_from_file_list(deliverable_files, selected_files) outer_div.add(deliverable_file_select_wdg) submit_button = SubmitWdg('Submit') submit_button.add_behavior(self.get_submit_button_behavior()) outer_div.add(submit_button) else: outer_div.add('<div>No deliverable files are available for this Order yet.</div>') return outer_div
def get_display(self): web = WebContainer.get_web() search_type = web.get_form_value("browser_search_type") search_text = web.get_form_value("browser_search_text") div = DivWdg() if search_type.startswith("prod/shot"): filter = self.get_filter(search_text, ['code','description']) elif search_type.startswith("prod/art_reference"): filter = self.get_filter(search_text, ['category','description']) else: filter = self.get_filter(search_text, ['name','code','description']) if not filter: return div search = Search(search_type) search.add_where(filter) div.add_style("width: 300") div.add_style("height: 200") div.add_style("overflow: auto") table = TableWdg(search_type, "list", css="minimal") table.set_show_property(False) table.set_sobjects(search.get_sobjects()) div.add(table) return div
def postprocess(self): web = WebContainer.get_web() value = web.get_form_value( self.get_input_name() ) if not value: return # get all fo the sobjects from the search keys instance_type = self.get_option("instance_type") # path is used for self-relating in an instance table src_path = self.get_option("path") #src_sobject = self.sobject search = Search(self.sobject.get_search_type()) search.add_id_filter(self.sobject.get_id()) src_sobject = search.get_sobject() # this is passed in from EditCmd in insert mode parent_key = self.get_option('parent_key') # in some rare cases we have project as the parent_key if parent_key and self.is_insert and 'sthpw/project' not in parent_key: # this is the parent dst_sobject = SearchKey.get_by_search_key(parent_key) # add all the new sobjects #instances = dst_sobject.get_related_sobject(instance_type) instance = SearchType.create(instance_type) instance.add_related_connection(src_sobject, dst_sobject, src_path=src_path) instance.commit()
def init(self): search = Search(Bin) search.add_column('type') search.add_group_by('type') self.set_search_for_options(search, 'type','type') self.add_empty_option('-- Any --')
def preprocess(self): sobjects = self.sobjects if not sobjects: return # find all of the instances in a shot sobject = sobjects[0] foreign_key = sobject.get_foreign_key() search_type = WebState.get().get_state("planner_search_type") search = Search( search_type ) search.add_column(foreign_key) if len(sobjects) == 1: search.add_filter(foreign_key, sobject.get_code()) else: search_codes = [x.get_code() for x in sobjects] search.add_filters(foreign_key, search_codes) search_type = sobject.get_search_type() search.add_order_by(foreign_key) children = search.get_sobjects() # convert to a dictionary for child in children: code = child.get_value(foreign_key) number = self.numbers.get(code) if not number: number = 0 number += 1 self.numbers[code] = number
def execute(self): left_cb_name , right_cb_name = self.get_checkbox_names() web = WebContainer.get_web() right_search_keys = web.get_form_values(right_cb_name) if not right_search_keys: return right_sobjects = [] for right_search_key in right_search_keys: right_sobject = Search.get_by_search_key(right_search_key) right_sobjects.append(right_sobject) search_type = self.get_search_type() left_search_keys = web.get_form_values(left_cb_name) for left_search_key in left_search_keys: left_sobject = Search.get_by_search_key( left_search_key ) for right_sobject in right_sobjects: #instance_name = "%s" % right_sobject.get_value("name") left_foreign_key = left_sobject.get_foreign_key() right_foreign_key = right_sobject.get_foreign_key() instance = SObjectFactory.create(search_type) instance.set_value(left_foreign_key, left_sobject.get_code() ) instance.set_value(right_foreign_key, right_sobject.get_code() ) name = left_sobject.get_code() instance.set_value("name", name) instance.commit()
def get_audio_configuration_table(element_eval_sobject): audio_configuration_lines_search = Search('twog/audio_evaluation_line') audio_configuration_lines_search.add_filter('element_evaluation_code', element_eval_sobject.get_code()) audio_configuration_lines = audio_configuration_lines_search.get_sobjects() # If no audio configuration lines exist for this element evaluation, return None so that the PDF won't display # a table if not audio_configuration_lines: return None audio_configuration_table_data = [ [ get_paragraph('<strong>Channel</strong>'), get_paragraph('<strong>Content</strong>'), get_paragraph('<strong>Tone</strong>'), get_paragraph('<strong>Peak</strong>') ] ] for line in audio_configuration_lines: channel = line.get('channel') content = line.get('content') tone = line.get('tone') peak = line.get('peak') # If all the items in a row are blank, skip it if any([channel, content, tone, peak]): line_data = [channel, content, tone, peak] audio_configuration_table_data.append(line_data) audio_configuration_table = Table(audio_configuration_table_data, hAlign='LEFT', spaceBefore=5, spaceAfter=5) return audio_configuration_table
def get_ref_obj(self, sobject): search_type = sobject.get_value("search_type") search_code = sobject.get_value("search_code", no_exception=True) if not search_code: search_id = sobject.get_value("search_code") else: search_id = None key = SearchKey.build_search_key(search_type, search_code) ref_sobject = self.ref_sobj_dict.get(str(key)) if not ref_sobject: try: if search_code: ref_sobject = Search.get_by_code(search_type, search_code) else: ref_sobject = Search.get_by_id(search_type, search_id) if not ref_sobject: return None except SearchException as e: print e.__str__() return None return ref_sobject
def get_deliverable_files_in_order(order_sobject): """ Given an order sobject, return all the deliverable files associated with it. :param order_sobject: twog/order sobject :return: List of twog/file sobjects """ files_in_order_search = Search('twog/file_in_order') files_in_order_search.add_filter('order_code', order_sobject.get_code()) files_in_order = files_in_order_search.get_sobjects() if files_in_order: files_in_order_string = ','.join( ["'{0}'".format(files_in_order.get('file_code')) for files_in_order in files_in_order] ) deliverable_files_search = Search('twog/file') deliverable_files_search.add_where('\"code\" in ({0})'.format(files_in_order_string)) deliverable_files_search.add_filter('classification', 'deliverable') deliverable_files = deliverable_files_search.get_sobjects() return deliverable_files else: return []
def init_cache(self): '''initialize the cache''' self.mtime = datetime.datetime.now() keys = self.caches.keys() self.caches = {} search = Search(self.search_type) search.set_show_retired(True) self.sobjects = search.get_sobjects() # build a search_key cache search_key_cache = {} search_keys = SearchKey.get_by_sobjects(self.sobjects) for search_key, sobject in zip(search_keys, self.sobjects): search_key_cache[search_key] = sobject self.caches['search_key'] = search_key_cache code_cache = {} for sobject in self.sobjects: code = sobject.get_code() code_cache[code] = sobject self.caches['code'] = code_cache for key in keys: if key in ['search_key', 'code']: continue self.build_cache_by_column(key)
def _test_task(my): project = Project.get() # create a new task task = SearchType.create("sthpw/task") task.set_parent(project) task.set_value("code", "XXX001") task.set_value("process", "unittest") task.set_value("description", "unittest") # set a time with no timezone. A timestamp with no timezone should # assume GMT. test_time = '2011-11-11 00:00:00' task.set_value("timestamp", test_time) # asset that the time has not changed timestamp = task.get_value("timestamp") my.assertEquals(timestamp, test_time) task.commit() # get the task back from the databse search = Search("sthpw/task") search.add_filter("code", "XXX001") task = search.get_sobject() # make sure the time has not changed. This value should is assumed # to be in GMT timestamp = task.get_value("timestamp") my.assertEquals(timestamp, test_time) task.delete()
def execute(my): my.search_type = my.kwargs.get('search_type') my.element_name = my.kwargs.get('element_name') #print "Calculating aggregate: ", my.search_type, my.element_name my.view = my.kwargs.get('view') if not my.view: my.view = 'definition' config = WidgetConfigView.get_by_search_type(search_type=my.search_type, view=my.view) widget = config.get_display_widget(my.element_name) # calculate all of the values search = Search(my.search_type) sobjects = search.get_sobjects() widget.set_sobjects(sobjects) widget.kwargs['use_cache'] = "false" for i, sobject in enumerate(sobjects): widget.set_current_index(i) value = widget.get_text_value() print sobject.get_code(), "value [%s]: " %value # all cache columns need are named with a c_ preceeding it # s_status # c_element_name # # this_month -> c_this_month #column = "c_%s" % my.element_name #sobject.set_value(column, value) sobject.set_value(my.element_name, value) sobject.commit()
def get_by_search_type(cls, search_type, project_code=''): # make sure this is a be search type assert search_type search_type_obj = SearchType.get(search_type) if not search_type_obj: return [] search_type = search_type_obj.get_base_key() cache_key = "%s|%s" % (search_type, project_code) # commenting out until we have a full implementation of # project pipelines """ search = Search("config/pipeline") if search_type: search.add_filter("search_type", search_type) search.add_project_filter(project_code) pipelines = cls.get_by_search(search, cache_key, is_multi=True) """ search = Search("sthpw/pipeline") if search_type: search.add_filter("search_type", search_type) search.add_project_filter(project_code) pipelines = cls.get_by_search(search, cache_key, is_multi=True) if not pipelines: return [] for pipe in pipelines: code = pipe.get_code() cls.cache_sobject('sthpw/pipeline|%s' %code, pipe) return pipelines
def check_existing_jobs(self): self.keep_jobs = [] for job in self.jobs: job_code = job.get_code() search = Search(self.get_job_search_type()) search.add_filter("code", job_code) job = search.get_sobject() if not job: print("Cancel ....") scheduler = Scheduler.get() scheduler.cancel_task(job_code) continue state = job.get_value("state") if state == 'cancel': print("Cancel task [%s] ...." % job_code) scheduler = Scheduler.get() scheduler.cancel_task(job_code) job.set_value("state", "terminated") job.commit() continue self.keep_jobs.append(job) self.jobs = self.keep_jobs
def execute(my): my.add_description("Set task's context to match process if empty") search = Search('sthpw/task') search.add_filter('context', None) tasks = search.get_sobjects() if tasks and len(tasks) > 700: print "More than 700 tasks are found. Exiting as a precaution." sys.exit(0) if not tasks: print "All tasks have context attribute filled in. Exiting." sys.exit(0) ctr = 0 for task in tasks: context = task.get_value('context') process = task.get_value('process') search_type = task.get_value('search_type') # delete dangling task if not search_type: task.delete() continue if not context and process: task.set_value('context', process) task.commit(triggers=False) ctr += 1 print "%s tasks have been processed. Their context are matched with their process." %ctr
def init(my): from pyasm.common import Environment from pyasm.search import Search my.login = Environment.get_login() my.user = my.login.get_login() my.sk = '' my.seen_groups = [] my.bigdict = {} my.indi_pct = 0.0 my.stat_colors = {'Pending':'#d7d7d7','In Progress':'#f5f3a4','In_Progress':'#f5f3a4','On Hold':'#e8b2b8','On_Hold':'#e8b2b8','Client Response': '#ddd5b8', 'Completed':'#b7e0a5','Need Buddy Check':'#e3701a','Ready':'#b2cee8','Internal Rejection':'#ff0000','External Rejection':'#ff0000','Fix Needed':'#c466a1','Failed QC':'#ff0000','Rejected': '#ff0000','DR In_Progress': '#d6e0a4', 'DR In Progress': '#d6e0a4','Amberfin01_In_Progress':'#D8F1A8', 'Amberfin01 In Progress':'#D8F1A8','Amberfin02_In_Progress':'#F3D291', 'Amberfin02 In Progress':'#F3D291','BATON In_Progress': '#c6e0a4', 'BATON In Progress': '#c6e0a4','Export In_Progress': '#796999','Export In Progress': '#796999', 'Buddy Check In_Progress': '#1aade3','Buddy Check In Progress': '#1aade3'} my.stat_relevance = {'Pending': 0,'In Progress': 4,'In_Progress': 4,'On Hold': 1,'On_Hold': 1,'Client Response': 2, 'Completed': -1,'Need Buddy Check': 10, 'Buddy Check In_Progress': 11, 'Buddy Check In Progress': 11, 'Ready': 3,'Internal Rejection': 12,'External Rejection': 13,'Failed QC': 14,'Fix Needed': 16,'Rejected': 15,'DR In_Progress': 5, 'DR In Progress': 5,'BATON In_Progress': 8, 'BATON In Progress': 8,'Export In_Progress': 9, 'Export In Progress': 9,'Amberfin01_In_Progress': 6, 'Amberfin01 In Progress': 6, 'Amberfin02_In_Progress':7, 'Amberfin02 In Progress':7 } my.timestamp = my.make_timestamp() my.date = my.timestamp.split(' ')[0] my.real_date = datetime.datetime.strptime(my.date, '%Y-%m-%d') my.all_groups = [] my.big_user = False users_s = Search('sthpw/login') users_s.add_filter('location','internal') users = users_s.get_sobjects() my.username_lookup = {'': '', None: '', 'NOTHING': ''} for user in users: login_name = user.get_value('login') fname = user.get_value('first_name') lname = user.get_value('last_name') my.username_lookup[login_name] = '%s %s' % (fname, lname)
def execute(my): web = WebContainer.get_web() if web.get_form_value("update") != "true": return my.element_name = my.kwargs.get("element_name") security_groups = web.get_form_values("security") from pyasm.security import AccessRuleBuilder, AccessManager rule_group = "side_bar" # get all of the groups search = Search("sthpw/login_group") login_groups = search.get_sobjects() for login_group in login_groups: access_rules = login_group.get_xml_value("access_rules") # add the rule to each group builder = AccessRuleBuilder(access_rules) code = login_group.get_value("login_group") if code in security_groups: builder.remove_rule(rule_group, my.element_name) else: builder.add_rule(rule_group, my.element_name, "deny") login_group.set_value("access_rules", builder.to_string()) login_group.commit()
def get_camera_wdg(self): widget = Widget() div = DivWdg(css="filter_box") sequence_filter = SequenceFilterWdg() epi_code, sequence_code = sequence_filter.get_value() div.add(sequence_filter) search = Search("prod/camera") columns = ['shot_code', 'description'] search_filter = SearchFilterWdg("camera_search", columns=columns,\ has_persistence=False) search_filter.alter_search(search) div.add(search_filter) widget.add(div) if sequence_code: search.add_where("shot_code in (select code from shot where sequence_code = '%s')" % sequence_code) table = TableWdg("prod/camera") table.set_search(search) widget.add(table) return widget
def get_art_reference(self): widget = Widget() help = HelpItemWdg('References', 'References tab lets the user organize art references. Each reference can be [related] to one or more assets defined in TACTIC. It can be set up when you [Edit] the reference.') self.add(help) div = DivWdg(css="filter_box") widget.add(div) columns = ['description','keywords'] search_filter = SearchFilterWdg("art_ref_search", columns=columns,\ has_persistence=False) div.add(search_filter) select = FilterSelectWdg("art_ref_category", label='Category: ', css='snall') select.set_option("setting", "art_reference_category") select.add_empty_option('-- Any --') div.add( select ) table = TableWdg("prod/art_reference") search = Search("prod/art_reference") search_filter.alter_search(search) value = select.get_value() if value != "": search.add_filter("category", value) table.set_search(search) widget.add(table) return widget
def postprocess(self): search_type = self.get_option("search_type") column = self.get_option("column") search_type = "construction/login_in_trade" column = "trade_code" value = self.get_value(self.name) sobject = self.sobject search = Search(search_type) search.add_relationship_filter(sobject) related = search.get_sobject() if not related: related = SearchType.create(search_type) related.set_parent(sobject) if not value: related.delete() else: related.set_value(column, value) related.commit()
def execute(my): search = Search(Submission) search.set_show_retired(True) submissions = search.get_sobjects() for submission in submissions: snapshot = Snapshot.get_latest_by_sobject(submission, "publish") paths = snapshot.get_all_lib_paths() bins = submission.get_bins() if not bins: print "Bin for submissin [%s] does not exist" % submission.get_id() continue bin = bins[0] code = bin.get_code() type = bin.get_value("type") label = bin.get_value("label") for path in paths: if not os.path.exists(path): print "WARNING: path '%s' does not exist" % path continue dirname = os.path.dirname(path) basename = os.path.basename(path) new_dirname = "%s/%s/%s/%s" % (dirname,type,label,code) if not os.path.exists(new_dirname): os.makedirs(new_dirname) new_path = "%s/%s" % (new_dirname, basename) print new_path FileUndo.move(path, new_path)
def handle_nodes(my, nodes): for node in nodes: node_name = my.xml.get_node_name(node) if node_name == 'search_type': my.remove_search_type(node) elif node_name == 'sobject': my.remove_sobjects(node) elif node_name == 'include': my.handle_include(node) elif node_name == 'python': my.handle_python(node) # remove plugin contents search = Search("config/plugin_content") search.add_filter("plugin_code", my.code) plugin_contents = search.get_sobjects() for plugin_content in plugin_contents: plugin_content.delete() # deregister the plugin plugin = Search.eval("@SOBJECT(config/plugin['code','%s'])" % my.code, single=True) if plugin: plugin.delete()
def setUp(my): # start batch environment Batch() from pyasm.web.web_init import WebInit WebInit().execute() my.sample3d_env = Sample3dEnvironment(project_code='sample3d') my.sample3d_env.create() my.test_env = UnittestEnvironment() my.test_env.create() # set up the proper project_type, with the use the ProdDirNaming and ProdFileNaming search = Search('sthpw/project') search.add_filter('code', 'unittest') my.sobj = search.get_sobject() # store the original setting in your database my.original_proj_type_dict = {'dir_naming_cls': my.sobj.get_value('dir_naming_cls'), 'file_naming_cls': my.sobj.get_value('file_naming_cls') } #my.transaction = Transaction.get(create=True) if my.sobj: my.sobj.set_value('dir_naming_cls', 'pyasm.prod.biz.ProdDirNaming') my.sobj.set_value('file_naming_cls', 'pyasm.prod.biz.ProdFileNaming') my.sobj.commit() else: my.sobj = SearchType.create('sthpw/project_type') my.sobj.set_value('dir_naming_cls', 'pyasm.prod.biz.ProdDirNaming') my.sobj.set_value('file_naming_cls', 'pyasm.prod.biz.ProdFileNaming') my.sobj.set_value('code', 'unittest') my.sobj.commit()
def get_display(my): #defining init is better than get_display() for this kind of SelectWdg search = Search( SearchType.SEARCH_TYPE ) if my.mode == None or my.mode == my.ALL_BUT_STHPW: # always add the login / login group search types filter = search.get_regex_filter("search_type", "login|task|note|timecard|trigger|milestone", "EQ") no_sthpw_filter = search.get_regex_filter("search_type", "^(sthpw).*", "NEQ") search.add_where('%s or %s' %(filter, no_sthpw_filter)) elif my.mode == my.CURRENT_PROJECT: project = Project.get() project_code = project.get_code() #project_type = project.get_project_type().get_type() project_type = project.get_value("type") search.add_where("\"namespace\" in ('%s','%s') " % (project_type, project_code)) search.add_order_by("search_type") search_types = search.get_sobjects() values = SObject.get_values(search_types, 'search_type') labels = [ x.get_label() for x in search_types ] values.append('CustomLayoutWdg') labels.append('CustomLayoutWdg') my.set_option('values', values) my.set_option('labels', labels) #my.set_search_for_options(search, "search_type", "get_label()") my.add_empty_option(label='-- Select Search Type --') return super(SearchTypeSelectWdg, my).get_display()
def _test_time(my): """ test timezone related behavior""" sobject = SearchType.create("sthpw/task") sobject.set_value("project_code", "unittest") sobject.set_value("bid_start_date", "2014-11-11 05:00:00") time = sobject.get_value("bid_start_date") my.assertEquals(time, "2014-11-11 05:00:00") sobject.commit() time = sobject.get_value("bid_start_date") my.assertEquals(time, "2014-11-11 05:00:00") from pyasm.search import DbContainer sql = DbContainer.get("sthpw") db_value = sql.do_query("SELECT bid_start_date from task where id = %s" % sobject.get_id()) # 2014-11-11 00:00:00 is actually written to the database my.assertEquals(db_value[0][0].strftime("%Y-%m-%d %H:%M:%S %Z"), "2014-11-11 00:00:00 ") # an sType specified without a project but with an id could be a common human error # but it should handle that fine obj1 = Search.eval('@SOBJECT(unittest/person?project=unittest["id", "%s"])' % sobject.get_id(), single=True) obj2 = Search.eval('@SOBJECT(unittest/person?id=2["id", "%s"])' % sobject.get_id(), single=True) obj3 = Search.eval('@SOBJECT(sthpw/task?id=2["id", "%s"])' % sobject.get_id(), single=True) task = Search.eval('@SOBJECT(sthpw/task["id", "%s"])' % sobject.get_id(), single=True) # EST and GMT diff is 5 hours my.assertEquals(task.get_value("bid_start_date"), "2014-11-11 05:00:00")
def get_display(my): top = my.top #top.add_gradient("background", "background", 5, -20) top.add_color("background", "background", -5) #top.add_style("padding-top: 10px") title = "Sample Chart" if title: date = "@FORMAT(@STRING($TODAY),'Dec 31, 1999')" date = Search.eval(date, single=True) title_wdg = DivWdg() top.add(title_wdg) title_wdg.add(title) title_wdg.add(" [%s]" % date) title_wdg.add_style("font-size: 1.1em") title_wdg.add_color("background", "background3") title_wdg.add_color("color", "color3") title_wdg.add_style("padding: 10px") title_wdg.add_style("font-weight: bold") title_wdg.add_style("text-align: center") #labels = ['chr001', 'chr002', 'chr003', 'chr004', 'prop001', 'prop002', 'cow001'] labels = [ 'week 1', 'week 2', 'week 3', 'week 4', 'week 5', 'week 6', 'week 7', 'week 8' ] values = [1, 2, 4, 5, 6, 7, 8] width = my.kwargs.get("width") if not width: width = '800px' height = my.kwargs.get("height") if not height: height = '500px' chart_div = DivWdg() top.add(chart_div) chart_div.add_style("text-align: center") chart = ChartWdg(height=height, width=width, chart_type='bar', labels=labels) chart_div.add(chart) data = ChartData(color="rgba(255, 0, 0, 1.0)", data=[1.2, 5.5, 7.5, 14.3, 10.2, 1.1, 3.3], x_data=[1, 3, 3.1, 3.2, 3.3, 3.4, 3.5]) chart.add(data) data = ChartData( color="rgba(0, 255, 0, 0.5)", data=[1.5, 4.3, 8.4, 6.2, 8.4, 2.2], ) chart.add(data) data = ChartData( color="rgba(0, 0, 255, 0.7)", data=[1.1, 3.5, 2.2, 6.6, 1.3, 9.4], ) chart.add(data) data = [14.3, 17, 15.5, -3, 17, 16.8, 11.4] data = ChartData(data=data, color="rgba(0, 0, 255, 0.3)") chart.add(data) data = {"m": -2.5, "b": 17.3} data = ChartData(chart_type='function', data=data, color="rgba(128, 128, 128, 0.6)") chart.add(data) data = {"m": -3, "b": 13.3} data = ChartData(chart_type='function', data=data, color="rgba(128, 128, 128, 0.6)") chart.add(data) data = {"a": -2, "b": 1.3, "c": 10} data = ChartData(chart_type='polynomial', data=data, color="rgba(128, 128, 128, 0.6)") chart.add(data) return top
def execute(my): sobject = my.get_caller() search_type = sobject.get_base_search_type() all_logins = False if search_type == 'config/widget_config': category = sobject.get_value("category") if not category: category = sobject.get_value("search_type") if category != 'SideBarWdg': return user = sobject.get_value('login') user = user.strip() if not user: all_logins = True from pyasm.biz import Project project = Project.get() project_code = project.get_code() login = Environment.get_user_name() tmp_dir = "%s/cache/side_bar" % Environment.get_tmp_dir() project_check = True if search_type =='sthpw/login_group': login_objs = sobject.get_logins() logins = [x.get_value('login') for x in login_objs] project_check = False else: if all_logins: expr = '@GET(sthpw/login.login)' logins = Search.eval(expr) else: logins = [login] filenames = [] if not os.path.exists(tmp_dir): os.makedirs(tmp_dir) return search = Search('sthpw/project') projects = search.get_sobjects() project_codes = [x.get_value('code') for x in projects] for login in logins: if project_check: filename = "%s__%s.html" % (project_code, login) filenames.append(filename) else: for project_code in project_codes: filename = "%s__%s.html" % (project_code, login) filenames.append(filename) #filenames = os.listdir(tmp_dir) for filename in filenames: #if not filename.startswith("%s__" % project_code): # print "skip filename ", filename path = "%s/%s" % (tmp_dir, filename) if os.path.exists(path): print "Deleting: ", path os.unlink(path)
def get_by_login(login): search = Search(RemoteRepo.SEARCH_TYPE) search.add_filter('login', login) repo = RemoteRepo.get_by_search(search, login) return repo
def get_all(cls): '''returns all of the projects in the system.''' search = Search(cls.SEARCH_TYPE) sobjects = search.get_sobjects() return sobjects
def get_project_db_resource(my, database=None): # get the db resource for attached to this particular project. # Not the db_resource for "sthpw/project" for which # project.get_db_resource() does from pyasm.security import Site site = Site.get_site() if site: key = "Project:db_resource_cache:%s" % site else: key = "Project:db_resource_cache" resource_dict = Container.get(key) if resource_dict: resource = resource_dict.get(my.get_code()) if resource != None: return resource else: resource_dict = {} Container.put(key, resource_dict) # the project defines the resource if not database: database = my.get_database_name() assert database if database == 'sthpw': # get if from the config db_resource_code = None else: db_resource_code = my.get_value("db_resource", no_exception=True) if not db_resource_code: # this could be any project, not just sthpw # already looked at cache, so set use_cache to False db_resource = Site.get_db_resource(site, database) if not db_resource: db_resource = DbResource.get_default(database, use_cache=False) #db_resource = DbResource.get_default(database, use_cache=False) resource_dict[key] = db_resource return db_resource #elif isinstance(db_resource_code, DbResource): elif DbResource.is_instance(db_resource_code): db_resource = db_resource_code resource_dict[key] = db_resource return db_resource db_resource_code = db_resource_code.strip() search = Search("sthpw/db_resource") search.add_filter("code", db_resource_code) db_resource_sobj = search.get_sobject() if not db_resource_sobj: raise TacticException("Database Resource [%s] does not exist" % db_resource_code) host = db_resource_sobj.get_value("host") vendor = db_resource_sobj.get_value("vendor") host = db_resource_sobj.get_value("host") port = db_resource_sobj.get_value("port") user = db_resource_sobj.get_value("login") password = db_resource_sobj.get_value("password") db_resource = DbResource(user=user, database=database, host=host, port=port, vendor=vendor, password=password) #Container.put(key, db_resource) resource_dict[key] = db_resource return db_resource
def get_search_types(my, include_sthpw=False, include_config=False, include_multi_project=False): '''get all the search types in this project''' if my.search_types != None: return my.search_types project_type = my.get_value("type") search = Search("sthpw/search_object") project_code = my.get_code() namespaces = [project_code] namespaces.append(project_type) if include_sthpw: namespaces.append("sthpw") if include_config: namespaces.append("config") if include_multi_project: if not include_config: search.add_filter('namespace', 'config', op='!=') if not include_sthpw: search.add_filter('namespace', 'sthpw', op='!=') search.add_op('begin') search.add_filter('database', '{project}') search.add_filters("namespace", namespaces) if include_multi_project: search.add_op('or') search.add_order_by("search_type") search_type_objs = search.get_sobjects() """ from pyasm.biz import Schema schema = Schema.get() xml = schema.get_xml_value("schema") search_types = xml.get_values("schema/search_type/@name") search = Search("sthpw/search_object") search.add_filters("code", search_types) search_type_objs = search.get_sobjects() """ search_types = [] for x in search_type_objs: # to avoid the old ill-defined prod/custom_property defined in sthpw namespace if (x.get_value('namespace') == 'sthpw' and x.get_value('search_type').find('custom_property') == -1)\ or my.has_table(x): search_types.append(x) return search_types
def get_display(my): category = "FreeformWdg" view = my.get_input_value("view") sobject = my.get_input_value("sobject") if not sobject and my.sobjects: sobject = my.sobjects[0] if not view: view = 'freeform' if sobject: search_key = sobject.get_search_key() search_type = sobject.get_base_search_type() else: search_key = my.get_input_value("search_key") search_type = my.get_input_value("search_type") if sobject: pass elif search_key: sobject = Search.get_by_search_key(search_key) elif search_type: search = Search(search_type) search.add_limit(1) sobject = search.get_sobject() else: sobject = None top = DivWdg() top.add_class("spt_freeform_top") search = Search("config/widget_config") search.add_filter("search_type", search_type) search.add_filter("view", view) config_sobj = search.get_sobject() if config_sobj: config_xml = config_sobj.get_value("config") else: config_xml = "" if not config_xml: top.add("No definition found") return top config = WidgetConfig.get(view=view, xml=config_xml) view_attrs = config.get_view_attributes() bgcolor = view_attrs.get("bgcolor") if not bgcolor: bgcolor = my.get_default_background() if bgcolor: top.add_style("background", bgcolor) # draw the layout freeform_layout = my.get_canvas_display(search_type, view, config, sobject) top.add(freeform_layout) return top
def dump_tactic_inserts(self, path, mode='sql', relative_dir_column=None): assert self.db_resource assert self.table database = self.db_resource.get_database() assert mode in ['sql', 'sobject'] if not relative_dir_column: if path: dirname = os.path.dirname(path) if not os.path.exists(dirname): os.makedirs(dirname) #f = open(path, 'w') #f = codecs.open(path, 'a', 'utf-8') UTF8Writer = codecs.getwriter('utf8') f = UTF8Writer(open(path, 'ab')) else: import sys f = sys.stdout from pyasm.search import Insert, Select, DbContainer, Search, Sql # get the data if not self.sobjects: search = Search("sthpw/search_object") search.add_filter("table_name", self.table) search.add_order_by("id") self.search_type_obj = search.get_sobject() if not self.search_type_obj: if self.no_exception == False: raise Exception( "Table [%s] does not have a corresponding search_type" % self.table) else: return search_type = self.search_type_obj.get_base_key() search = Search(search_type) search.set_show_retired(True) self.sobjects = search.get_sobjects() # get the info for the table from pyasm.search import SearchType, Sql column_info = SearchType.get_column_info(self.search_type) for sobject in self.sobjects: if relative_dir_column: if path: #dirname = os.path.dirname(path) subpath = "%s/%s.spt" % ( path, sobject.get_value(relative_dir_column).replace( ".", "/")) if not os.path.exists(os.path.dirname(subpath)): os.makedirs(os.path.dirname(subpath)) UTF8Writer = codecs.getwriter('utf8') f = UTF8Writer(open(subpath, 'ab')) else: import sys f = sys.stdout f.write("%s\n" % self.delimiter) if mode == 'sobject': search_type = sobject.get_base_search_type() f.write("insert = SearchType.create('%s')\n" % search_type) if self.skip_invalid_column: f.write("insert.skip_invalid_column()\n") else: f.write("insert.set_table('%s')\n" % self.table) data = sobject.get_data() for name, value in data.items(): if self.replace_dict: for column, replace_args in self.replace_dict.items(): if name == column: replace_str = replace_args[0] regex = replace_args[1] if regex: #if not re.match(regex,value): # raise TacticException("%s does not conform to standard format. Expected format must match %s"%(column,regex)) value = re.sub(regex, replace_str, value) else: value = replace_str if name in self.ignore_columns: continue if name == '_tmp_spt_rownum': continue if not self.include_id and name == "id": #insert.set_value("id", '"%s_id_seq".nextval' % table, quoted=False) pass elif value == None: continue else: # This is not strong enough #if value.startswith("{") and value.endswith("}"): # f.write("insert.set_expr_value('%s', \"\"\"%s\"\"\")\n" % (name, value)) if type(value) == types.IntType or \ type(value) == types.FloatType or \ type(value) == types.BooleanType or \ type(value) == types.LongType: f.write("insert.set_value('%s', %s)\n" % (name, value)) else: # if the value contains triple double quotes, convert to # triple quotes if isinstance(value, datetime.datetime): value = str(value) elif isinstance(value, unicode): #value = str(value) value = value.encode("UTF-8") # this fixes a problem with non-ascii characters if isinstance(value, basestring): quoted = value.startswith('"') and value.endswith( '"') value = repr(value) quoted2 = value.startswith('"') and value.endswith( '"') if not quoted and quoted2: value = value.strip('"') # repr puts single quotes at the start and end if value.startswith("'") and value.endswith("'"): value = value[1:-1] # and it puts a slash in front value = value.replace(r"\'", "'") # replace literal \n with newline (comes from repr) value = value.replace(r"\n", "\n") value = value.replace('"""', "'''") #value = value.replace("\\", "\\\\") # handle the case where the value starts with a quote if value.startswith('"'): value = '\\%s' % value # handle the case where the value ends starts with a quote if value.endswith('"'): value = '%s\\"' % value[:-1] f.write("insert.set_value('%s', \"\"\"%s\"\"\")\n" % (name, value)) # Disable commit for now #if mode == 'sobject': # f.write("insert.commit()\n") f.write("%s\n" % self.end_delimiter) f.write("\n") if relative_dir_column: f.close() if not relative_dir_column and path: f.close()
def execute(my): count = 0 change_count = 0 from pyasm.search import Search, SearchException search = Search("sthpw/snapshot") search.add_order_by("search_type") search.add_order_by("search_id") search.add_order_by("context") search.add_order_by("version desc") snapshots = search.get_sobjects() print "found [%s] snapshots" % len(snapshots) current_search_type = None current_search_id = None current_context = None current_version = None for i, snapshot in enumerate(snapshots): search_type = snapshot.get_value("search_type") search_id = snapshot.get_value("search_id") context = snapshot.get_value("context") version = snapshot.get_value("version") #print i, search_type, search_id, context, version if not (search_type == current_search_type and \ search_id == current_search_id and \ context == current_context): count += 1 if snapshot.get_value('is_latest') != True: change_count += 1 try: snapshot.set_latest() print "\t... set to is latest! ", search_type, search_id, context, version except Exception, e: print "\t ... WARNING: could not set latest:: ", search_type, search_id, context, version print "\t ... ", e current_search_type = search_type current_search_id = search_id current_context = context current_version = version
def get_session_wdg(self): div = DivWdg() div.add_style("width: 150px") search = Search("config/ingest_rule") rules = search.get_sobjects() add = ActionButtonWdg(title="+", tip="Add new rule", size='small') div.add(add) add.add_style("margin-top: -6px") add.add_behavior({ 'type': 'click_up', 'session_code': self.session.get_code(), 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_ingestion_top"); spt.tab.set_tab_top(top); var class_name = 'tactic.ui.tools.IngestionToolWdg'; var kwargs = { session_code: bvr.session_code }; spt.tab.select("rules"); spt.tab.load_selected("rules", "Rules", class_name, kwargs); ''' }) add.add_style("float: right") div.add("<b>Rules</b><hr/>") if not rules: div.add("<br/><i>No rules found</i><br/>") for rule in rules: rule_code = rule.get_code() rule_title = rule.get_value("title") rule_div = DivWdg() div.add(rule_div) rule_div.add_style("padding: 3px") hover = rule_div.get_color("background", -10) rule_div.add_behavior({ 'type': 'hover', 'hover': hover, 'cbjs_action_over': ''' bvr.src_el.setStyle("background", bvr.hover); ''', 'cbjs_action_out': ''' bvr.src_el.setStyle("background", ""); ''' }) rule_div.add_class("hand") checkbox = CheckboxWdg("whatever") rule_div.add(checkbox) rule_div.add(rule_title) rule_div.add_behavior({ 'type': 'click_up', 'rule_code': rule_code, 'session_code': self.session_code, 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_ingestion_top"); spt.tab.set_tab_top(top); var class_name = 'tactic.ui.tools.IngestionToolWdg'; var kwargs = { location: 'server', rule_code: bvr.rule_code, session_code: bvr.session_code }; spt.tab.select("rules"); spt.tab.load_selected("rules", "Rules", class_name, kwargs); ''' }) return div
def execute(my): start = time.time() from pyasm.common import SPTDate timestamp = SPTDate.now() timestamp = SPTDate.add_gmt_timezone(timestamp) timestamp = SPTDate.convert_to_local(timestamp) format = '%Y-%m-%d %H:%M:%S' timestamp = timestamp.strftime(format) updates = my.kwargs.get("updates") if isinstance(updates, basestring): updates = jsonloads(updates) last_timestamp = my.kwargs.get("last_timestamp") #assert last_timestamp if not last_timestamp: my.info = {"updates": {}, "timestamp": timestamp} return last_timestamp = parser.parse(last_timestamp) last_timestamp = SPTDate.add_gmt_timezone(last_timestamp) #last_timestamp = last_timestamp - timedelta(hours=24) #print "last: ", last_timestamp # get out all of the search_keys client_keys = set() for id, values_list in updates.items(): if isinstance(values_list, dict): values_list = [values_list] for values in values_list: handler = values.get("handler") if handler: handler = Common.create_from_class_path(handler) search_key = handler.get_search_key() else: search_key = values.get("search_key") if search_key: client_keys.add(search_key) # find all of the search that have changed changed_keys = set() for check_type in ['sthpw/change_timestamp', 'sthpw/sobject_log']: search = Search(check_type) search.add_filter("timestamp", last_timestamp, op=">") search.add_filters("search_type", ["sthpw/sobject_log", "sthpw/status_log"], op="not in") #print search.get_statement() changed_sobjects = search.get_sobjects() for sobject in changed_sobjects: search_type = sobject.get_value("search_type") search_code = sobject.get_value("search_code") if search_type.startswith("sthpw/"): search_key = "%s?code=%s" % (search_type, search_code) else: search_key = "%s&code=%s" % (search_type, search_code) changed_keys.add(u'%s' % search_key) intersect_keys = client_keys.intersection(changed_keys) #for x in client_keys: # print x #print "---" #print "changed_keys: ", changed_keys #print "---" #print "intersect_keys: ", intersect_keys from pyasm.web import HtmlElement results = {} for id, values_list in updates.items(): if isinstance(values_list, dict): values_list = [values_list] for values in values_list: handler = values.get("handler") if handler: handler = Common.create_from_class_path(handler) search_key = handler.get_search_key() else: search_key = values.get("search_key") if search_key and search_key not in intersect_keys: continue # evaluate any compare expressions compare = values.get("compare") if compare: search_key = values.get("search_key") if search_key: sobject = Search.get_by_search_key(search_key) else: sobject = None cmp_result = Search.eval(compare, sobject, single=True) if cmp_result == True: continue # some value to display value = "Loading ..." else: value = HtmlElement.eval_update(values) if value == None: continue results[id] = value my.info = {"updates": results, "timestamp": timestamp} #print "time: ", time.time() - start #print results return results
def handle_search(my): my.search = Search(my.search_type) my.alter_search(my.search) return my.search
def get_format_value(my, value, format, format_option=None): '''format is required. format_option is optional where applicable like fps for timecode''' if value == '': return value if isinstance(value, datetime.datetime): value = str(value) elif not isinstance(value, basestring): value = str(value) if value.startswith("{") and value.endswith("}"): from pyasm.search import Search value = Search.eval(value) # ------------------------------------------------ # Integer if format == '-1234': if not value: # Case where value is '', 0, 0.0, -0.0 . value = 0 value = "%0.0f" % my.convert_to_float(value) elif format == '-1,234': if not value: value = 0 # Group the value into three numbers seperated by a comma. value = my.number_format(value, places=0) # ------------------------------------------------ # Float elif format == '-1234.12': if not value: value = 0 value = "%0.2f" % my.convert_to_float(value) elif format == '-1,234.12': # break the value up by 3s if not value: value = 0 elif isinstance(value, basestring): value = float(value) value = my.number_format(value, places=2) # ------------------------------------------------ # Percentage elif format == '-13%': if not value: value = 0 value = my.convert_to_float(value) * 100 value = "%0.0f" % my.convert_to_float(value) + "%" elif format == '-12.95%': if not value: value = 0 value = my.convert_to_float(value) * 100 value = "%0.2f" % my.convert_to_float(value) + "%" # ------------------------------------------------ # Currency elif format == '-$1,234': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True) value = value[0:-3] elif format == '-$1,234.00': if not value: value = 0 value = my.currency_format(value, grouping=True) elif format == '-$1,234.--': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True) value = value[0:-3] + ".--" elif format == '-$1,234.00 CAD': # break the value up by 3s if not value: value = 0 value = my.currency_format(value, grouping=True, monetary=True) elif format == '($1,234.00)': # break the value up by 3s if not value: value = "-" else: value = my.currency_format(value, grouping=True) if value.startswith("-"): value = "(%s)" % value.replace("-", "") # ------------------------------------------------ # Date elif format == '31/12/99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y") elif format == 'December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%B %d, %Y") elif format == '31/12/1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%Y") elif format == 'Dec 31, 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%b %d, %y") elif format == 'Dec 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%b %d, %Y") elif format == '31 Dec, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d %b, %Y") elif format == '31 December 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d %B %Y") elif format == 'Fri, Dec 31, 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a, %b %d, %y") elif format == 'Fri 31/Dec 99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a %d/%b %y") elif format == 'Fri, December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%a, %B %d, %Y") elif format == 'Friday, December 31, 1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%A, %B %d, %Y") elif format == '12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%d") elif format == '99-12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%y-%m-%d") elif format == '1999-12-31': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y-%m-%d") elif format == '12-31-1999': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%d-%Y") elif format == '12/99': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%m-%y") elif format == '31/Dec': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%b") elif format == 'December': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%B") elif format == '52': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%U") # ------------------------------------------------ # Time elif format == '13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%H:%M") elif format == '13:37:46': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%H:%M:%S") elif format == '01:37 PM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%I:%M %p") elif format == '01:37:46 PM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%I:%M:%S %p") elif format == '31/12/99 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y %H:%M") elif format == '99/12/31 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%y/%m/%d %H:%M") elif format == '1999/12/31 13:37': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y/%m/%d %H:%M") elif format == 'YYYY/MM/DD HH:MM AM': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%Y/%m/%d %I:%M %p") elif format == '31/12/99 13:37:46': if not value: value = '' else: value = parser.parse(value) value = value.strftime("%d/%m/%y %H:%M:%S") elif format == 'DATETIME': if not value: value = '' else: value = parser.parse(value) from pyasm.biz import ProdSetting setting = ProdSetting.get_value_by_key('DATETIME') if not setting: setting = "%Y-%m-%d %H:%M" value = value.strftime(setting) elif format == 'DATE': if not value: value = '' else: value = parser.parse(value) from pyasm.biz import ProdSetting setting = ProdSetting.get_value_by_key('DATE') if not setting: setting = "%Y-%m-%d" value = value.strftime(setting) # ------------------------------------------------ # Scientific elif format == '-1.23E+03': if not value: value = '' else: try: value = "%.2e" % my.convert_to_float(value) except: value = "0.00" elif format == '-1.234E+03': if not value: value = '' else: try: value = "%.2e" % my.convert_to_float(value) except: value = "0.00" # ------------------------------------------------ # Boolean # false = 0, true = 1 elif format in ['True|False']: if value: value = 'True' else: value = 'False' elif format in ['true|false']: if value: value = 'true' else: value = 'false' # ------------------------------------------------ # Timecode elif format in [ 'MM:SS.FF', 'MM:SS:FF', 'MM:SS', 'HH:MM:SS.FF', 'HH:MM:SS:FF', 'HH:MM:SS' ]: #fps = my.get_option('fps') fps = format_option if not fps: fps = 24 else: fps = int(fps) timecode = TimeCode(frames=value, fps=fps) value = timecode.get_timecode(format) # ------------------------------------------------ # Dictionary elif format == "DICT": dict_as_str = "" dict_list = [] if not value: value = '' else: for key, value in sorted(value.iteritems()): dict_list.append("%s : %s" % (key, value)) dict_as_str = "<br />".join(dict_list) value = dict_as_str # ------------------------------------------------ # File Size elif format in ['KB']: value = float(value) ext = " B" if not value: value = 0 ext = "B" elif value > 1024**5 / 2: value = float(value) / 1024**5 ext = "PB" elif value > 1024**4 / 2: value = float(value) / 1024**4 ext = "TB" elif value > 1024**3 / 2: value = float(value) / 1024**3 ext = "GB" elif value > 1024**2 / 2: value = float(value) / 1024**2 ext = "MB" elif value > 1024 / 2: value = float(value) / 1024 ext = "KB" else: value = int(value) return "%s B" % value value = my.currency_format(value, grouping=True) # HACK: remove $ and last decimal value = value[1:-1] value = "%s %s" % (value, ext) elif format in ['ROOT']: value, ext = os.path.splitext(value) elif format in ['EXT']: base, value = os.path.splitext(value) value = value.lstrip(".") elif format in ['BASENAME']: value = os.path.basename(value) elif format in ['DIRNAME']: value = os.path.dirname(value) return value
def execute_mms_oracle_dump(self): assert self.db_resource assert self.table database = self.db_resource.get_database() if not self.sql_out_fp or not self.pl_sql_var_out_fp or not self.pl_sql_ins_out_fp: raise Exception( "SQL and PL-SQL file pointers are required for generating output." ) from pyasm.search import Insert, Select, DbContainer, Search, Sql # get the data if not self.sobjects: search = Search("sthpw/search_object") search.add_filter("table_name", self.table) self.search_type_obj = search.get_sobject() if not self.search_type_obj: if self.no_exception == False: raise Exception( "Table [%s] does not have a corresponding search_type" % self.table) else: return search_type = self.search_type_obj.get_base_key() search = Search(search_type) search.set_show_retired(True) self.sobjects = search.get_sobjects() # get the info for the table column_info = self.search_type_obj.get_column_info() for sobject in self.sobjects: column_list = [] value_list = [] update_col_list = [] update_map = {} timestamp_regex = re.compile( "^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})") data = sobject.data sobject_id = data.get("id") do_pl_sql = False for name, value in data.items(): if value == None: continue else: col_name = '"%s"' % name column_list.append(col_name) if isinstance(value, types.StringTypes): if timestamp_regex.match(value): value_list.append( "TO_TIMESTAMP('%s','RR-MM-DD HH24:MI:SS')" % str(value).split('.')[0][2:]) else: new_value = self.get_oracle_friendly_string_value( value) if len(new_value) > 3800: #{ do_pl_sql = True var_name = "%s_%s_%s__var" % \ ( self.table, col_name.replace('"',''), str(sobject_id).zfill(5) ) self.pl_sql_var_out_fp.write( "\n%s VARCHAR2(%s) := %s ;\n" % (var_name, len(new_value), new_value)) new_value = var_name #} value_list.append(new_value) # elif type(value) == datetime.datetime: # value_list.append( "TO_TIMESTAMP('%s','RR-MM-DD HH24:MI:SS.FF')" % # str(value).split('.')[0][2:] ) else: value_list.append("%s" % value) if do_pl_sql: self.pl_sql_ins_out_fp.write('\n') from sql import Sql if database_type == "SQLServer": self.pl_sql_ins_out_fp.write( 'INSERT INTO "%s" (%s) VALUES (%s);\n' % (self.database, self.table, ','.join(column_list), ','.join(value_list))) else: self.pl_sql_ins_out_fp.write( 'INSERT INTO "%s" (%s) VALUES (%s);\n' % (self.table, ','.join(column_list), ','.join(value_list))) else: self.sql_out_fp.write('\n') from sql import Sql if database_type == "SQLServer": self.sql_out_fp.write( 'INSERT INTO "%s" (%s) VALUES (%s);\n' % (self.database, self.table, ','.join(column_list), ','.join(value_list))) else: self.sql_out_fp.write( 'INSERT INTO "%s" (%s) VALUES (%s);\n' % (self.table, ','.join(column_list), ','.join(value_list)))
def get_sobject_from_form(self): search_type = self.get_form_value("search_type") search_id = self.get_form_value("search_id") from pyasm.search import Search sobject = Search.get_by_id(search_type, search_id) return sobject
def execute(self): assert self.db_resource assert self.table database = self.db_resource.get_database() from pyasm.search import Insert, Select, DbContainer, Search, Sql # get the data if not self.sobjects: search = Search("sthpw/search_object") # BAD assumption #search.add_filter("table", self.table) # create a search_type. This is bad assumption cuz it assumes project-specific search_type # should call set_search_type() if not self.search_type: self.search_type = "%s/%s" % (self.database, self.table) search.add_filter("search_type", self.search_type) self.search_type_obj = search.get_sobject() if not self.search_type_obj: if self.no_exception == False: raise SqlException( "Table [%s] does not have a corresponding search_type" % self.table) else: return search_type = self.search_type_obj.get_base_key() search = Search(self.search_type) search.set_show_retired(True) self.sobjects = search.get_sobjects() # get the info for the table column_info = SearchType.get_column_info(self.search_type) for sobject in self.sobjects: print self.delimiter insert = Insert() insert.set_database(self.database) insert.set_table(self.table) data = sobject.data for name, value in data.items(): if name in self.ignore_columns: continue if not self.include_id and name == "id": insert.set_value("id", '"%s_id_seq".nextval' % table, quoted=False) #insert.set_value(name, value, quoted=False) elif value == None: continue else: # replace all of the \ with double \\ insert.set_value(name, value) print "%s" % insert.get_statement() print self.end_delimiter print
def run(my): import time time.sleep(3) print "Starting Scheduler ...." # NOTE: not sure why we have to do a batch here from pyasm.security import Batch Batch(login_code="admin") timed_triggers = [] from pyasm.biz import Project search = Search("sthpw/project") projects = search.get_sobjects() # get the all of the timed triggers #search = Search("sthpw/timed_trigger") #search.add_filter("type", "timed") for project in projects: project_code = project.get_code() try: search = Search("config/trigger?project=%s" % project_code) search.add_filter("event", "schedule") timed_trigger_sobjs = search.get_sobjects() except Exception, e: print "WARNING: ", e continue # example """ if project_code == 'broadcast2': tt = SearchType.create("config/trigger") tt.set_value("class_name", "tactic.command.PythonTrigger") # data = timed_trigges.get("data") tt.set_value("data", '''{ "type": "interval", "interval": 5, "delay": 5, "mode": "threaded", "script_path": "trigger/scheduled" } ''') timed_trigger_sobjs.append(tt) """ has_triggers = False for trigger_sobj in timed_trigger_sobjs: trigger_class = trigger_sobj.get_value("class_name") if not trigger_class and trigger_sobj.get_value("script_path"): trigger_class = 'tactic.command.PythonTrigger' data = trigger_sobj.get_json_value("data") data['project_code'] = trigger_sobj.get_project_code() try: timed_trigger = Common.create_from_class_path(trigger_class, [], data) timed_trigger.set_input(data) has_triggers = True except ImportError: raise Exception("WARNING: [%s] does not exist" % trigger_class) timed_triggers.append(timed_trigger) if has_triggers: print "Found [%s] scheduled triggers in project [%s]..." % (len(timed_triggers), project_code)
def execute(my): from pyasm.security import Batch Batch(login_code="admin") os.environ["TACTIC_MONITOR"] = "true" if not my.num_processes: my.num_processes = Config.get_value("services", "process_count") if my.num_processes: my.num_processes = int(my.num_processes) else: my.num_processes = 3 start_port = Config.get_value("services", "start_port") ports_str = os.environ.get("TACTIC_PORTS") if not ports_str: ports_str = Config.get_value("services", "ports") if ports_str: ports = ports_str.split("|") ports = [int(x) for x in ports] else: if start_port: start_port = int(start_port) else: start_port = 8081 ports = [] for i in range(0, my.num_processes): ports.append( start_port + i ) tactic_threads = [] #start_tactic = Config.get_value("services", "tactic") #start_job_queue = Config.get_value("services", "job_queue") #start_watch_folder = Config.get_value("services", "watch_folder") start_tactic = False start_job_queue = False start_watch_folder = False start_async = False services = Config.get_value("services", "enable") custom_services = [] if services: #services = services.split("|") services = re.split("[|,]", services) for service in services: if service == 'tactic': start_tactic = True elif service == 'job_queue': start_job_queue = True elif service == 'watch_folder': start_watch_folder = True elif service == 'async': start_async = True else: custom_services.append(service) else: start_tactic = True # create a number of processes if start_tactic: #for i in range(0, my.num_processes): for port in ports: # start cherrypy tactic_thread = TacticThread(port) tactic_thread.set_dev(my.dev_mode) tactic_thread.start() tactic_threads.append(tactic_thread) time.sleep(1) #port += 1 # aSync Queue services if start_async: num_processes = Config.get_value("async", "process_count") if not num_processes: num_processes = 1 else: num_processes = int(num_processes) for i in range(0, num_processes): job_thread = ASyncThread() job_thread.start() tactic_threads.append(job_thread) # Job Queue services if start_job_queue: num_processes = Config.get_value("services", "queue_process_count") if not num_processes: num_processes = 1 else: num_processes = int(num_processes) for i in range(0, num_processes): job_thread = JobQueueThread() job_thread.start() tactic_threads.append(job_thread) # Watch Folder services if start_watch_folder: search = Search("sthpw/watch_folder") watch_folders = search.get_sobjects() for watch_folder in watch_folders: project_code = watch_folder.get("project_code") base_dir = watch_folder.get("base_dir") search_type = watch_folder.get("search_type") process = watch_folder.get("process") if not project_code: print "Watch Folder missing project_code ... skipping" continue if not project_code: print "Watch Folder missing base_dir ... skipping" continue if not search_type: print "Watch Folder missing search_type ... skipping" continue watch_thread = WatchFolderThread( project_code=project_code, base_dir=base_dir, search_type=search_type, process=process ) watch_thread.start() tactic_threads.append(watch_thread) # set up custom services for service in custom_services: kwargs = Config.get_section_values(service) custom_thread = CustomPythonProcessThread(**kwargs) custom_thread.start() tactic_threads.append(custom_thread) if len(tactic_threads) == 0: print print "No services started ..." print return # create a separate thread for timed processes # DEPRECATED tactic_timed_thread = TacticTimedThread() tactic_timed_thread.start() tactic_threads.append(tactic_timed_thread) # create a separate thread for scheduler processes start_scheduler = Config.get_value("services", "scheduler") if start_scheduler == 'true': tactic_scheduler_thread = TacticSchedulerThread() tactic_scheduler_thread.start() tactic_threads.append(tactic_scheduler_thread) DbContainer.close_thread_sql() # check each thread every 20 seconds while 1: end = False try: if my.check_interval: time.sleep(my.check_interval) for tactic_thread in tactic_threads: tactic_thread._check() else: # FIXME: break for now (for windows service) break except KeyboardInterrupt, e: print "Keyboard interrupt ... exiting Tactic" for tactic_thread in tactic_threads: tactic_thread.end = True end = True if end: break
def get_display(my): #defining init is better than get_display() for this kind of SelectWdg search = Search(SearchType.SEARCH_TYPE) if my.mode == None or my.mode == my.ALL_BUT_STHPW: # always add the login / login group search types filter = search.get_regex_filter( "search_type", "login|task|note|timecard|trigger|milestone", "EQ") no_sthpw_filter = search.get_regex_filter("search_type", "^(sthpw).*", "NEQ") search.add_where('%s or %s' % (filter, no_sthpw_filter)) elif my.mode == my.CURRENT_PROJECT: project = Project.get() project_code = project.get_code() #project_type = project.get_project_type().get_type() project_type = project.get_value("type") search.add_where("\"namespace\" in ('%s','%s') " % (project_type, project_code)) search.add_order_by("search_type") search_types = search.get_sobjects() values = SObject.get_values(search_types, 'search_type') labels = [x.get_label() for x in search_types] values.append('CustomLayoutWdg') labels.append('CustomLayoutWdg') my.set_option('values', values) my.set_option('labels', labels) #my.set_search_for_options(search, "search_type", "get_label()") my.add_empty_option(label='-- Select Search Type --') return super(SearchTypeSelectWdg, my).get_display()
def run(my): import time time.sleep(6) #print "Starting Timed Trigger" # checks are done every 60 seconds chunk = 60 # FIXME: not sure why we have to do a batch here from pyasm.security import Batch Batch(login_code="admin") # get the all of the timed triggers #search = Search("sthpw/timed_trigger") #search.add_filter("type", "timed") search = Search("sthpw/trigger") search.add_filter("event", "timed") timed_trigger_sobjs = search.get_sobjects() timed_triggers = [] for trigger_sobj in timed_trigger_sobjs: trigger_class = trigger_sobj.get_value("class_name") try: timed_trigger = Common.create_from_class_path(trigger_class) except ImportError: raise Exception("WARNING: [%s] does not exist" % trigger_class) timed_triggers.append(timed_trigger) while 1: time.sleep(chunk) #print "Running timer" date = Date() #print "utc: ", date.get_display_time() # go through each trigger for timed_trigger in timed_triggers: print timed_trigger if not timed_trigger.is_ready(): print "... not ready" continue if timed_trigger.is_in_separate_thread(): class xxx(threading.Thread): def run(my): try: Batch() timed_trigger._do_execute() finally: DbContainer.close_thread_sql() xxx().start() else: timed_trigger._do_execute() DbContainer.close_thread_sql() if my.end: print "Stopping timed thread" break
def init(my): search = Search(CommandSObj) search.add_column('notification_code') search.add_group_by('notification_code') my.set_search_for_options(search, 'notification_code', 'notification_code')
def get_display(my): query = my.get_option("query") depend_col = my.get_option("dependency") # for example # FIXME: this has to be fleshed out ... it's a little too complicated # at the moment!!! query = "MMS/product_type|id|product_name" depend_col = "discipline_id" depend_element = 'discipline' top = DivWdg() top.add_class("spt_input_top") top.add_attr( "spt_cbjs_get_input_key", "var value=spt.dg_table.get_element_value(cell_to_edit, '%s');return value" % depend_element) top.add_style("background: black") # get all of the sobjects search_type, value_col, label_col = query.split("|") search = Search(search_type) sobjects = search.get_sobjects() # arrange the sobjects according to keys selections = {} for sobject in sobjects: depend_value = sobject.get_value(depend_col) selection_list = selections.get(depend_value) if not selection_list: selection_list = [] selections[depend_value] = selection_list selection_list.append(sobject) # put in a default default_div = DivWdg() default_div.add_class("spt_input_option") default_div.add_attr("spt_input_key", "default") default_div.add("No options for selected [%s]" % depend_element) top.add(default_div) # add list of possible select statements for key, selection_list in selections.items(): div = DivWdg() div.add_class("spt_input_option") div.add_attr("spt_input_key", key) values = [] labels = [] for sobject in selection_list: values.append(sobject.get_value(value_col)) labels.append(sobject.get_value(label_col)) select = SelectWdg(my.get_input_name()) select.add_empty_option('-- Select --') select.set_option("values", values) select.set_option("labels", labels) div.add(select) from tactic.ui.panel import CellEditWdg CellEditWdg.add_edit_behavior(select) top.add(div) return top
def get_display(my): my.labels_attr = my.get_option('label_attr') if my.labels_attr: my.labels_attr = my.labels_attr.split('|') from tactic.ui.panel import EditWdg if hasattr(my, 'parent_wdg') and isinstance(my.get_parent_wdg(), EditWdg): sobject = my.get_current_sobject() parent = sobject.get_parent() group = None pipeline_code = None if parent: pipeline_code = parent.get_value('pipeline_code') pipeline = Pipeline.get_by_code(pipeline_code) labels_expr = None if pipeline: attrs = pipeline.get_process_attrs( sobject.get_value('process')) group = attrs.get('%s_login_group' % my.get_name()) if group: values_expr = "@GET(sthpw/login_group['login_group', '%s'].sthpw/login_in_group.sthpw/login.login)" % group if my.labels_attr: labels_expr = [ "@GET(sthpw/login_group['login_group', '%s'].sthpw/login_in_group.sthpw/login.%s)" % (group, x.strip()) for x in my.labels_attr ] labels_expr = ' +   + '.join(labels_expr) else: values_expr = "@GET(sthpw/login.login)" if my.labels_attr: labels_expr = [ "@GET(sthpw/login.%s)" % (x.strip()) for x in my.labels_attr ] labels_expr = ' +   + '.join(labels_expr) select = SelectWdg(my.get_input_name()) select.add_empty_option("-- Select a User --") """ values = [] labels = [] for user in group_users: values.append(user) labels.append(' %s'%user) """ select.set_option('values_expr', values_expr) if labels_expr: select.set_option('labels_expr', labels_expr) current_value = sobject.get_value(my.get_name()) if current_value: select.set_value(current_value) return select #all_users = Search.eval("@GET(sthpw/login.login)") all_users = Search.eval("@SOBJECT(sthpw/login)") all_users_label = [] # don't use expression here since it's not as db-efficient as retrieving the sobjects """ if my.labels_attr: labels_expr = ["@GET(sthpw/login.login.%s)"%x.strip() for x in my.labels_attr] """ ''' groups = Search.eval("@SOBJECT(sthpw/login_group)") group_dict = {} for group in groups: group_users = Search.eval("@GET(sthpw/login_group['login_group', '%s'].sthpw/login_in_group.sthpw/login.login)"%group.get_value('login_group')) group_dict[group.get_value('login_group')] = group_users ''' logins_dict = {} for user in all_users: user_name = user.get_value('login') logins_dict[user_name] = {} group_dict = {} items = Search.eval("@SOBJECT(sthpw/login_in_group)") for item in items: item_login = item.get_value("login") if logins_dict.get(item_login) == None: continue item_group = item.get_value("login_group") group_list = group_dict.get(item_group) if group_list == None: group_list = [] group_dict[item_group] = group_list group_list.append(item_login) top = DivWdg() top.add_class("spt_input_top") # HACK! This isn't very well constructed ### Tore: Not my code! Copied from ProcessContextInputWdg. Seems to work though. top.add_attr("spt_cbjs_get_input_key", "return cell_to_edit.getAttribute('spt_pipeline_code');") # Adding an "all users" select option in case it can't find a useful select widget. div = DivWdg() div.add_class("spt_input_option") #div.add_attr("spt_input_key", '__all__') #Not needed, since it defaults to the first one anyway. select = SelectWdg(my.get_name()) select.add_empty_option("-- Select a User --") values = [] labels = [] labels_dict = {} for user in all_users: user_name = user.get_value('login') values.append(user_name) label = user_name if my.labels_attr: user_labels = [user.get_value(x) for x in my.labels_attr] label = ' '.join(user_labels) labels_dict[user_name] = label labels.append('%s' % label) #print "select ", user_name # -- NOTE: leaving this commented out code here for reference. Not sure why this is the case but when # -- this click behavior is used instead of a 'change' behavior that forces a blur on select, # -- click selection only works for this widget in Firefox and does NOT work in IE # # select.add_behavior( { 'type': 'click', # 'cbjs_action': 'spt.dg_table.select_wdg_clicked( evt, bvr.src_el );' } ) # -- Replace previous 'click' behavior with a 'change' behavior to force blur() of select element ... # -- this works for both Firefox and IE # select.add_behavior({ 'type': 'change', 'cbjs_action': 'bvr.src_el.blur();' }) #behavior = { # 'type': 'keyboard', # 'kbd_handler_name': 'DgTableSelectWidgetKeyInput', #} #select.add_behavior( behavior ) select.set_option("values", values) select.set_option("labels", labels) div.add(select) top.add(div) #Building each of the select widgets per group here. for group in group_dict.keys(): div = DivWdg() div.add_class("spt_input_option") div.add_attr("spt_input_key", group) select = SelectWdg(my.get_name()) select.add_empty_option("-- Select a User --") values = [''] labels = ['<< %s >>' % group] for user in group_dict[group]: values.append(user) label = labels_dict.get(user) labels.append(' %s' % label) select.add_behavior({ 'type': 'click', 'cbjs_action': 'spt.dg_table.select_wdg_clicked( evt, bvr.src_el );' }) #behavior = { # 'type': 'keyboard', # 'kbd_handler_name': 'DgTableSelectWidgetKeyInput', #} #select.add_behavior( behavior ) select.set_option("values", values) select.set_option("labels", labels) div.add(select) top.add(div) return top
def execute(db_resource): # This works if there is a project set up already with the appropriate # db_resource. search_type = "table/foofoo?project=db2_test" search_type_obj = SearchType.get(search_type) search = Search(search_type) sobjects = search.get_sobjects() print "length: ", len(sobjects) # or (note that there is no project here). The two arguments # are sufficient to determine a search. Here we want to just "casually" # connect to a separate database resource. table = 'foofoo' search = db_resource.get_search(table) sobjects = search.get_sobjects() print "length: ", len(sobjects) for sobject in sobjects: print sobject.get_code(), sobject.get_value("description") table = 'widget_config' search = db_resource.get_search(table) sobjects = search.get_sobjects() print "length: ", len(sobjects) for sobject in sobjects: print sobject.get_code(), sobject.get_value("config") db_resource = DbResource(vendor="MySQL", database="fifi", user="******") introspect = DbIntrospect() introspect.register("fifi", db_resource) table = 'cards' search = db_resource.get_search(table) sobjects = search.get_sobjects() print "length: ", len(sobjects) for sobject in sobjects: print sobject.get_code(), sobject.get_value("description") print "sqlite: transaction_log" db_resource = DbResource.get_by_code('sqlite', 'sthpw') introspect = DbIntrospect() introspect.register("sqlite", db_resource) search = db_resource.get_search("transaction_log") sobjects = search.get_sobjects() print "length: ", len(sobjects) print "selfsql: fifi" db_resource = DbResource.get_by_code('mysql', 'fifi') introspect = DbIntrospect() introspect.register("fifi", db_resource) search = db_resource.get_search("cards") sobjects = search.get_sobjects() print "length: ", len(sobjects) print "selfsql: fifi" search_type = "table/node0?project=db3_test" search = Search(search_type) sobjects = search.get_sobjects() print "length: ", len(sobjects)
def get_display(self): session_code = self.kwargs.get("session_code") session_code = 'session101' session = Search.get_by_code("config/ingest_session", session_code) data = session.get_json_value("data") if data == None: data = {} top = self.top top.add_class("spt_ingest_dir_list_top") self.set_as_panel(top) inner = DivWdg() top.add(inner) inner.add_style("padding: 10px") inner.add_color("background", "background") base_dir = self.kwargs.get("base_dir") location = self.kwargs.get("location") rescan = self.kwargs.get("rescan") if rescan in [True, 'true']: rescan = True else: rescan = False rescan = ActionButtonWdg(title='Rescan', tip="Rescan file system") inner.add(rescan) rescan.add_style("float: right") rescan.add_behavior({ 'type': 'click_up', 'base_dir': base_dir, 'cbjs_action': ''' spt.app_busy.show("Scanning", "Scanning files in " + bvr.base_dir); var top = bvr.src_el.getParent(".spt_ingest_dir_list_top"); spt.panel.refresh(top); spt.app_busy.hide(); ''' }) import datetime last_scan = datetime.datetime.now() last_scan_wdg = DivWdg() inner.add(last_scan_wdg) last_scan_wdg.add("Last Scan: %s" % last_scan) last_scan_wdg.add_style("margin-bottom: 5px") found_wdg = DivWdg() inner.add(found_wdg) found_wdg.add_style("margin-bottom: 5px") inner.add("<hr/>") show_handled = self.kwargs.get("show_handled") show_handled = False if show_handled in [False, 'false']: try: scan_path = "/tmp/scan" import codecs f = codecs.open(scan_path, 'r', 'utf-8') ignore = jsonloads(f.read()) f.close() except Exception as e: print("Error: ", e.message) ignore = None else: ignore = None # check for rescan cache_key = self.kwargs.get("cache_key") rescan = True if rescan == True: paths = [] else: paths = data.get(cache_key) if not paths: paths = [] dir_list_wdg = DirListWdg(paths=paths, base_dir=base_dir, location=location, ignore=ignore, depth=2) # cache the paths if rescan: paths = dir_list_wdg.get_paths() data['paths'] = paths session.set_json_value("data", data) session.commit() # add the paths found num_paths = dir_list_wdg.get_num_paths() found_wdg.add("Found: %s items" % num_paths) inner.add(dir_list_wdg) return top
def get_sobjects(my): columns = [ 'product_name', 'sample_size', 'labor_average', 'material_average_cost', 'average_time_taken' ] sql = ''' SELECT "product_name", "number_of_each_product_type" "sample_size", "average_time_taken" "labor_average", sum("material_cost_per_item") "material_average_cost", sum("vendor_cost_per_item") "vender_average_cost" FROM ( SELECT "product_name", "subtask"."id" "subtask_id", "number_of_each_product_type", "average_time_taken", "product_quantity", --"total_material_cost", "total_vendor_costs", "total_material_cost" / "product_quantity" "material_cost_per_item", "total_vendor_costs" / "product_quantity" "vendor_cost_per_item" FROM "product_type" LEFT OUTER JOIN "product_type_aggrgt" ON "product_type"."id" = "product_type_aggrgt"."product_type_id" LEFT OUTER JOIN "subtask_product" ON "product_type"."id" = "subtask_product"."product_type_id" LEFT OUTER JOIN "subtask" ON "subtask"."id" = "subtask_product"."subtask_id" LEFT OUTER JOIN "subtask_material_aggrgt" ON "subtask"."id" = "subtask_material_aggrgt"."subtask_id" LEFT OUTER JOIN "subtask_vndrcost_aggrgt" ON "subtask"."id" = "subtask_vndrcost_aggrgt"."subtask_id" ) X group by X."product_name", X."number_of_each_product_type", X."average_time_taken", X."product_quantity", "subtask_id" order by X."product_name" ''' db = DbContainer.get("MMS") from pyasm.search import Select, Search search_type = my.kwargs.get('search_type') select = Select() select.set_statement(sql) statement = select.get_statement() search = Search(search_type) search.select = select sobjects = search.get_sobjects() for sobject in sobjects: sobject.set_value("id", -1) return sobjects
def get_display(self): top = self.top self.set_as_panel(top) top.add_class("spt_ingestion_top") top.add_color("background", "background", -5) self.data = {} rules_div = DivWdg() top.add(rules_div) rules_div.add_style("padding: 10px") rules_div.add("Rules: ") rules_select = SelectWdg("rule_code") rule_code = self.get_value('rule_code') if rule_code: rules_select.set_value(rule_code) rules_select.set_option("query", "config/ingest_rule|code|title") rules_select.add_empty_option("-- New --") rules_div.add(rules_select) rules_select.add_behavior({ 'type': 'change', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_ingestion_top"); value = bvr.src_el.value; var class_name = 'tactic.ui.tools.IngestionToolWdg'; spt.panel.load(top, class_name, {rule_code: value} ); ''' }) rules_div.add("<hr/>") # read from the database if rule_code: search = Search("config/ingest_rule") search.add_filter("code", rule_code) sobject = search.get_sobject() else: sobject = None if sobject: self.data = sobject.get_value("data") if self.data: self.data = jsonloads(self.data) session_code = self.kwargs.get("session_code") if session_code: session = Search.get_by_code("config/ingest_session", session_code) else: if sobject: session = sobject.get_related_sobject("config/ingest_session") print("sobject: ", sobject.get_code(), sobject.get_value("spt_ingest_session_code")) print("parent: ", session) else: session = None if not session: #session = SearchType.create("config/ingest_session") #session.set_value("code", "session101") #session.set_value("location", "local") ##session.set_value("base_dir", "C:") top.add("No session defined!!!") return top rule = "" filter = "" ignore = "" # get the base path if sobject: base_dir = sobject.get_value("base_dir") else: base_dir = '' #else: # base_dir = self.get_value("base_dir") #if not base_dir: # base_dir = '' if sobject: title = sobject.get_value("title") else: title = '' if sobject: code = sobject.get_value("code") else: code = '' file_list = self.get_value("file_list") scan_type = self.get_value("scan_type") action_type = self.get_value("action_type") rule = self.get_value("rule") if not rule: rule = base_dir # get the rule for this path checkin_mode = "dir" depth = 0 table = Table() rules_div.add(table) table.add_color("color", "color") from tactic.ui.input.text_input_wdg import TextInputWdg # add the title table.add_row() td = table.add_cell() td.add("Title: ") td = table.add_cell() text = TextInputWdg(name="title") td.add(text) if title: text.set_value(title) text.add_class("spt_title") text.add_style("width: 400px") #text.add_color("background", "background", -10) # add the optional code table.add_row() td = table.add_cell() td.add("Code (optional): ") td = table.add_cell() text = TextInputWdg(name="code") td.add(text) if code: text.set_value(code) text.set_readonly() text.add_color("background", "background", -10) text.add_class("spt_code") text.add_style("width: 400px") table.add_row() td = table.add_cell() td.add_style("height: 10px") td.add("<hr/>") table.add_row() td = table.add_cell() td.add("<b>Scan:</b><br/>") td.add( "The following information will be used to find the paths that will be operated on by the ingestion process<br/><br/>" ) # add a scan type table.add_row() td = table.add_cell() td.add("Type: ") select = SelectWdg("scan_type") select.add_class("spt_scan_type") td = table.add_cell() td.add(select) select.set_value(self.get_value("action")) labels = ['Simple List', 'Rule', 'Script'] values = ['list', 'rule', 'script'] select.set_option("values", values) select.set_option("labels", labels) if scan_type: select.set_value(scan_type) table.add_row() table.add_cell(" ") select.add_behavior({ 'type': 'change', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_ingestion_top"); value = bvr.src_el.value; var elements = top.getElements(".spt_scan_list"); for (var i = 0; i < elements.length; i++) { if (value == 'list') spt.show(elements[i]); else spt.hide(elements[i]); } var elements = top.getElements(".spt_scan_rule"); for (var i = 0; i < elements.length; i++) { if (value == 'rule') spt.show(elements[i]); else spt.hide(elements[i]); } var elements = top.getElements(".spt_scan_script"); for (var i = 0; i < elements.length; i++) { if (value == 'script') spt.show(elements[i]); else spt.hide(elements[i]); } ''' }) # add in a list of stuff tbody = table.add_tbody() tbody.add_class("spt_scan_list") if scan_type != 'list': tbody.add_style("display: none") tr = table.add_row() td = table.add_cell() td.add("List of files: ") td = table.add_cell() text = TextAreaWdg(name="file_list") td.add(text) text.add_style("width: 400px") #text.set_readonly() #text.add_color("background", "background", -10) text.set_value(file_list) table.close_tbody() # add rule scan mode tbody = table.add_tbody() tbody.add_class("spt_scan_rule") if scan_type != 'rule': tbody.add_style("display: none") # add the path tr = table.add_row() td = table.add_cell() td.add("Starting Path: ") td = table.add_cell() hidden = HiddenWdg("session_code", session.get_code()) td.add(hidden) text = TextInputWdg(name="base_dir") td.add(text) text.set_value(base_dir) text.add_style("width: 400px") #text.set_readonly() #text.add_color("background", "background", -10) text.set_value(base_dir) # add rule tr = table.add_row() td = table.add_cell() td.add("Tag Rule: ") td = table.add_cell() text = TextInputWdg(name="rule") td.add(text) text.add_style("width: 400px") text.set_value(rule) tr = table.add_row() td = table.add_cell() td.add("Filter: ") td = table.add_cell() text = TextWdg("filter") td.add(text) text.set_value(self.get_value("filter")) text.add_style("width: 400px") text.add_style("padding: 2px") text.add_style("-moz-border-radius: 5px") tr = table.add_row() td = table.add_cell() td.add("Ignore: ") td = table.add_cell() text = TextWdg("ignore") td.add(text) text.set_value(self.get_value("ignore")) text.set_value(ignore) text.add_style("width: 400px") text.add_style("padding: 2px") text.add_style("-moz-border-radius: 5px") table.add_row() td = table.add_cell() td.add("Validation script: ") td.add_style("vertical-align: top") td.add_style("padding-top: 5px") td = table.add_cell() text = TextInputWdg(name="validation_script") text.set_value(self.get_value("validation_script")) text.add_style("width: 400px") td.add(text) icon = IconButtonWdg(title='Edit Validation Script', icon=IconWdg.EDIT) icon.add_style("float: right") td.add(icon) icon.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' spt.named_events.fire_event("show_script_editor"); var top = bvr.src_el.getParent(".spt_ingestion_top"); var values = spt.api.Utility.get_input_values(top, null, false); var kwargs = { script_path: values.validation_script } setTimeout( function() { spt.js_edit.display_script_cbk(evt, kwargs) }, 500 ); ''' }) table.close_tbody() # add the script path tbody = table.add_tbody() tbody.add_class("spt_scan_script") if scan_type != 'script': tbody.add_style("display: none") tr = table.add_row() td = table.add_cell() td.add("Script Path: ") td = table.add_cell() text = TextInputWdg(name="script_path") td.add(text) text.add_style("width: 400px") table.close_tbody() table.add_row() td = table.add_cell("<hr/>") table.add_row() td = table.add_cell() td.add("<b>Action</b><br/>") td.add( "The following information define the actions that will be used on each matched path<br/><br/>" ) # pick the type of action table.add_row() td = table.add_cell() td.add("Type: ") select = SelectWdg("action_type") td = table.add_cell() td.add(select) labels = ['Checkin', 'Ignore'] values = ['checkin', 'ignore'] select.set_option("values", values) select.set_option("labels", labels) select.add_empty_option("-- Select --") if action_type: select.set_value(action_type) select.add_behavior({ 'type': 'change', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_ingestion_top"); value = bvr.src_el.value; var elements = top.getElements(".spt_action_ignore"); for (var i = 0; i < elements.length; i++) { if (value == 'ignore') spt.show(elements[i]); else spt.hide(elements[i]); } var elements = top.getElements(".spt_action_checkin"); for (var i = 0; i < elements.length; i++) { if (value == 'checkin') spt.show(elements[i]); else spt.hide(elements[i]); } ''' }) table.add_row() td = table.add_cell("<br/>") # add the script path tbody = table.add_tbody() tbody.add_class("spt_action_checkin") if action_type != 'checkin': tbody.add_style("display: none") # add the checkin type table.add_row() td = table.add_cell() td.add("Action: ") select = SelectWdg("action") td = table.add_cell() td.add(select) select.set_value(self.get_value("action")) labels = ['File Checkin', 'Directory Checkin', 'Sequence Checkin'] values = ['file', 'directory', 'sequence', 'ignore'] select.set_option("values", values) select.set_option("labels", labels) table.add_row() td = table.add_cell() td.add("Mode: ") select = SelectWdg("mode") td = table.add_cell() td.add(select) labels = ['Copy', 'Move', 'In Place'] values = ['copy', 'move', 'inplace'] select.set_option("values", values) select.set_option("labels", labels) # add the search_type table.add_row() td = table.add_cell() td.add("sType: ") td = table.add_cell() select = SelectWdg("search_type") td.add(select) search_types = Project.get().get_search_types() values = [x.get_value("search_type") for x in search_types] select.set_option("values", values) search_type = self.kwargs.get("search_type") if search_type: select.set_value(search_type) # add the search_type table.add_row() td = table.add_cell() td.add("Context: ") td = table.add_cell() select = SelectWdg("context") td.add(select) select.set_option("values", ['publish', 'by rule', 'custom']) # add extra values extra_div = DivWdg() text = TextWdg("extra_name") text.add_attr("spt_is_multiple", "true") extra_div.add(text) extra_div.add(" = ") text = TextWdg("extra_value") extra_div.add(text) text.add_attr("spt_is_multiple", "true") template_div = DivWdg() text = TextWdg("extra_name") text.add_attr("spt_is_multiple", "true") template_div.add(text) template_div.add(" = ") text = TextWdg("extra_value") template_div.add(text) text.add_attr("spt_is_multiple", "true") table.close_tbody() table.add_row() td = table.add_cell("<br/>") table.add_row() td = table.add_cell() td.add("Extra Keywords: ") td.add_style("vertical-align: top") td.add_style("padding-top: 5px") td = table.add_cell() text = TextWdg("keywords") text.add_style("width: 300px") td.add(text) table.add_row() td = table.add_cell() td.add("Extra Values: ") td.add_style("vertical-align: top") td.add_style("padding-top: 5px") td = table.add_cell() extra_list = DynamicListWdg() td.add(extra_list) extra_list.add_item(extra_div) extra_list.add_template(template_div) table.add_row() table.add_cell(" ") table.add_row() td = table.add_cell() td.add("Process script: ") td.add_style("vertical-align: top") td.add_style("padding-top: 5px") td = table.add_cell() text = TextWdg("process_script") text.add_style("width: 300px") td.add(text) text.set_value(self.get_value("process_script")) icon = IconButtonWdg(title='Edit Process Script', icon=IconWdg.EDIT) icon.add_style("float: right") td.add(icon) icon.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' spt.named_events.fire_event("show_script_editor"); var top = bvr.src_el.getParent(".spt_ingestion_top"); var values = spt.api.Utility.get_input_values(top, null, false); var kwargs = { script_path: values.process_script } // need to wait for this setTimeout( function() { spt.js_edit.display_script_cbk(evt, kwargs) }, 500 ); ''' }) table.add_row() td = table.add_cell() td.add("Custom Naming: ") td.add_style("vertical-align: top") td.add_style("padding-top: 5px") td = table.add_cell() text = TextWdg("naming") text.add_style("width: 300px") td.add(text) table.add_row() td = table.add_cell() #td.add("<br clear='all'/>") td.add("<hr/>") behavior = { 'type': 'click_up', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_ingestion_top"); var values = spt.api.Utility.get_input_values(top, null, false); spt.app_busy.show("Scanning ...", values.base_dir); var class_name = 'tactic.ui.tools.IngestionProcessWdg'; var server = TacticServerStub.get(); values.mode = bvr.mode; values.is_local = 'true'; // scan client side if (values.is_local == 'true') { var base_dir = values.base_dir; var applet = spt.Applet.get(); var files = applet.list_recursive_dir(base_dir); // turn into a string var files_in_js = []; for (var i = 0; i < files.length; i++) { var file = files[i].replace(/\\\\/g, "/"); files_in_js.push( file ); } values.files = files_in_js; values.base_dir = base_dir; /* var server = TacticServerStub.get(); var handoff_dir = server.get_handoff_dir(); var applet = spt.Applet.get(); for (var i = 0; i < files_in_js.length; i++) { try { var parts = files_in_js[i].split("/"); var filename = parts[parts.length-1]; spt.app_busy.show("Copying files to handoff", filename); applet.copy_file(files_in_js[i], handoff_dir+"/"+filename); } catch(e) { log.error(e); } } */ } var info_el = top.getElement(".spt_info"); spt.panel.load(info_el, class_name, values); spt.app_busy.hide(); ''' } # Save button button = ActionButtonWdg(title="Save", tip="Save Rule") td.add(button) button.add_style("float: right") behavior['mode'] = 'save' button.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_ingestion_top"); var values = spt.api.Utility.get_input_values(top, null, false); spt.app_busy.show("Saving ..."); var class_name = 'tactic.command.CheckinRuleSaveCmd'; var server = TacticServerStub.get(); server.execute_cmd(class_name, values); spt.panel.refresh(top, {}); spt.app_busy.hide(); ''' }) # Scan button button = ActionButtonWdg(title="Scan", tip="Click to Scan") td.add(button) button.add_style("float: left") # set a limit #limit = TextWdg("limit") #td.add(limit) #text.add_style("float: left") behavior = behavior.copy() behavior['mode'] = 'scan' button.add_behavior(behavior) # Test button button = ActionButtonWdg(title="Test", tip="Do a test of this rule") td.add(button) behavior = behavior.copy() behavior['mode'] = 'test' button.add_behavior(behavior) button.add_style("float: left") # Ingest button button = ActionButtonWdg(title="Ingest", tip="Click to start ingesting") td.add(button) behavior = behavior.copy() behavior['mode'] = 'checkin' button.add_behavior(behavior) table.add_behavior({ 'type': 'listen', 'event_name': 'file_browser|select', 'cbjs_action': ''' var dirname = bvr.firing_data.dirname; var top = bvr.src_el.getParent(".spt_ingestion_top"); var kwargs = { base_dir: dirname }; spt.panel.load(top, top.getAttribute("spt_class_name"), kwargs); ''' }) top.add(self.get_info_wdg()) return top
def get_all_projects(cls): search = Search("sthpw/project") search.add_filters("code", ['admin', 'sthpw'], op='not in') projects = search.get_sobjects() return projects
class DbResourceWdg(BaseRefreshWdg): def get_display(my): top = my.top top.add_style("padding: 20px") wizard = WizardWdg(title="Database Resource Manager") top.add(wizard) wizard.add(my.get_vendor_wdg(), "Vendor" ) wizard.add(my.get_connect_wdg(), "Connection" ) wizard.add(my.get_tables_wdg(), "Tables" ) return top def get_vendor_wdg(my): div = DivWdg() div.set_name("Vendor") vendors = [ "SQLite", "PostgreSQL", "MySQL", "Oracle", "SQLServer", "MongoDb" ] # unfortunately, Sqlite is capitalized incorectly in the code vendor_codes = [ "Sqlite", "PostgreSQL", "MySQL", "Oracle", "SQLServer", "MongoDb" ] vendor_icons = [ "Sqlite", "PostgreSQL", "MySQL", "Oracle", "SQLServer", "MongoDb" ] # get 3rd party vendors for vendor in vendors: vendor_div = DivWdg() div.add(vendor_div) vendor_div.add_style("margin: 10px") radio = RadioWdg("vendor") div.add(radio) radio.set_option("value", vendor) div.add(vendor) return div def get_connect_wdg(my): div = DivWdg() div.set_name("Connection") table = Table() div.add(table) from tactic.ui.panel import EditWdg edit = EditWdg(search_type="sthpw/db_resource", view="edit") table.add_row() table.add_cell(edit) return div def get_tables_wdg(my): div = DivWdg() div.set_name("Tables") div.add("In order to fully register a database, you must bind it to a TACTIC project") div.add("<br/>") project_code = "mongodb" database = "test_database" db_resource = DbResource( server='localhost', vendor='MongoDb', database=database ) try: connect = DbContainer.get(db_resource) except Exception, e: div.add("Could not connect") div.add_style("padding: 30px") div.add("<br/>"*2) div.add(str(e)) return div # Bind project to this resource database_text = TextWdg("database") div.add("Database: ") div.add(database_text) div.add("<br/>"*2) project_text = TextWdg("project") div.add("Project Code: ") div.add(project_text) div.add("<br/>") div.add("<hr/>") # connect and introspect the tables in this database tables = connect.get_tables() table = Table() div.add(table) table.set_max_width() for table_name in tables: table.add_row() search_type = "table/%s?project=%s" % (table_name, project_code) td = table.add_cell() icon = IconWdg("View Table", IconWdg.FOLDER_GO) td.add(icon) icon.add_behavior( { 'type': 'click_up', 'search_type': search_type, 'cbjs_action': ''' var class_name = 'tactic.ui.panel.ViewPanelWdg'; var kwargs = { search_type: bvr.search_type } spt.panel.load_popup("table", class_name, kwargs); ''' } ) td = table.add_cell() td.add(table_name) td = table.add_cell() search = Search(search_type) count = search.get_count() td.add(" %s item/s" % count) columns = search.get_columns() td = table.add_cell() td.add(columns) # search_type td = table.add_cell() text = TextWdg("search_type") td.add(text) new_search_type = "%s/%s" % (project_code, table_name) text.set_value(new_search_type) register_div = DivWdg() div.add(register_div) register_div.add_style("padding: 20px") button = ActionButtonWdg(title="Register") register_div.add(button) return div
def get_display(my): top = DivWdg() top.add_border() top.add_style("padding: 10px") top.add_color("color", "color") top.add_color("background", "background") top.add_class("spt_reports_top") title = DivWdg() title.add("Dashboards") title.add_style("font-size: 18px") title.add_style("font-weight: bold") title.add_style("text-align: center") title.add_style("padding: 10px") title.add_style("margin: -10px -10px 10px -10px") title.add_gradient("background", "background3", 5, -10) top.add(title) from tactic.ui.widget import TitleWdg subtitle = TitleWdg(name_of_title='List of Dashboards', help_alias='project-startup-dashboards') top.add(subtitle) top.add("<br/>") dashboards = [] # read the config file from pyasm.widget import WidgetConfig tmp_path = __file__ dir_name = os.path.dirname(tmp_path) file_path = "%s/../config/dashboard-conf.xml" % (dir_name) config = WidgetConfig.get(file_path=file_path, view="definition") element_names = config.get_element_names() for element_name in element_names: attrs = config.get_element_attributes(element_name) dashboard_data = {} kwargs = config.get_display_options(element_name) class_name = kwargs.get('class_name') dashboard_data['class_name'] = class_name dashboard_data['kwargs'] = kwargs dashboard_data['title'] = attrs.get("title") dashboard_data['description'] = attrs.get("description") dashboard_data['image'] = attrs.get("image") dashboard_data['image'] = attrs.get("image") dashboards.append(dashboard_data) # get all of the configs from the database search = Search("config/widget_config") search.add_filter("widget_type", "dashboard") db_configs = search.get_sobjects() for db_config in db_configs: dashboard_data = {} view = db_config.get_value("view") kwargs = {'view': view} parts = view.split(".") title = Common.get_display_title(parts[-1]) xml = db_config.get_value("config") dashboard_data['class_name'] = "tactic.ui.panel.CustomLayoutWdg" dashboard_data['kwargs'] = kwargs dashboard_data['title'] = title dashboard_data['description'] = title dashboard_data['image'] = None dashboard_data['xml'] = xml dashboard_data['widget_type'] = db_config.get_value("widget_type") dashboards.append(dashboard_data) # create a bunch of panels table = Table() top.add(table) table.add_color("color", "color") table.add_style("margin-bottom: 20px") table.center() for i, dashboard in enumerate(dashboards): if i == 0 or i % 4 == 0: tr = table.add_row() td = table.add_cell() td.add_style("vertical-align: top") td.add_style("padding: 3px") title = dashboard description = dashboard.get("title") # Each node will contain a list of "items" and will be stored as a table in the database.''' class_name = dashboard.get("class_name") kwargs = dashboard.get("kwargs") title = dashboard.get("title") description = dashboard.get("description") xml = dashboard.get("xml") or "" image = dashboard.get("image") icon = dashboard.get("icon") if image: div = DivWdg() if isinstance(image, basestring): image = image.upper() image = eval("IconWdg('', IconWdg.%s)" % image) div.add_style("margin-left: 15px") div.add_style("margin-top: 5px") else: image = image div.add(image) image = div elif icon: icon = icon.upper() image = eval("IconWdg('', IconWdg.%s)" % icon) else: div = DivWdg() #image = IconWdg("Bar Chart", IconWdg.WARNING) image = IconWdg("Bar Chart", IconWdg.DASHBOARD_02) div.add_style("margin-left: 15px") div.add_style("margin-top: 5px") div.add(image) image = div behavior = { 'type': 'click_up', 'title': title, 'class_name': class_name, 'kwargs': kwargs, 'cbjs_action': ''' var top = bvr.src_el.getParent(".spt_reports_top"); spt.tab.set_main_body_tab(); //spt.tab.set_tab_top(top); var kwargs = {}; spt.tab.add_new(bvr.title, bvr.title, bvr.class_name, bvr.kwargs); ''' } schema_wdg = my.get_section_wdg(title, description, image, behavior) schema_wdg.add_behavior({ 'type': 'load', 'title': title, 'class_name': class_name, 'xml': xml, 'kwargs': kwargs, 'cbjs_action': ''' var report_top = bvr.src_el; report_top.kwargs = bvr.kwargs; report_top.class_name = bvr.class_name; report_top.element_name = bvr.title; report_top.xml = bvr.xml; ''' }) td.add(schema_wdg) #from tactic.ui.container import TabWdg #tab = TabWdg(show_add=False) #top.add(tab) return top