def _test_compare(self): '''Test early exiting of compare statements.''' # Clear expression cache ExpressionParser.clear_cache() transaction = Transaction.get(create=True) sobject = Search.get_by_search_key(self.search_key) tasks = Search.eval("@SOBJECT(sthpw/task)", sobject) new_status = 'complete' for task in tasks: task.set_value("status", new_status) task.commit() transaction.commit() time.sleep(3) cmd = DynamicUpdateCmd(last_timestamp=self.last_timestamp, updates=self.updates) Command.execute_cmd(cmd) self.last_timestamp = cmd.get_info("timestamp") updates = cmd.get_info("updates") self.assertEquals(updates["001"], 0) self.assertEquals(updates["002"], new_status) self.assertEquals(updates.get("003"), None) self.assertEquals(updates["004"], True) self.assertEquals(updates.get("005"), None) self.assertEquals(updates["006"], 0)
def init(my): list_item_table = '' my.full_item_list = [] if my.kwargs.has_key( 'list_item_table' ): list_item_table = my.kwargs.get( 'list_item_table' ) expr = '@SOBJECT(MMS/%s)' % list_item_table parser = ExpressionParser() my.full_item_list = parser.eval(expr) my.el_name = '' if my.kwargs.has_key( 'element_name' ): my.el_name = my.kwargs.get( 'element_name' ) my.input_el_name = '' if my.kwargs.has_key( 'input_element_to_find' ): my.input_el_name = my.kwargs.get( 'input_element_to_find' ) my.col_to_match = '' if my.kwargs.has_key( 'column_to_match_value' ): my.col_to_match = my.kwargs.get( 'column_to_match_value' ) my.col_for_label = '' if my.kwargs.has_key( 'column_for_label' ): my.col_for_label = my.kwargs.get( 'column_for_label' ) my.select_element = HtmlElement('select')
def get_group_bottom_wdg(self, sobjects): expression = self.get_option("group_bottom") if not expression: return None # parse the expression self.vars = self.get_vars() parser = ExpressionParser() raw_result = parser.eval(expression, sobjects=sobjects, vars=self.vars) format_str = self.kwargs.get("display_format") if format_str: from tactic.ui.widget import FormatValueWdg format_wdg = FormatValueWdg(format=format_str, value=raw_result) result = format_wdg else: result = str(raw_result) div = DivWdg() div.add(result) div.add_style("text-align: right") #div.add_class( "spt_%s_expr_bottom" % (self.get_name()) ) # add a listener #for sobject in sobjects: # if sobject.is_insert(): # continue # # if self.enable_eval_listener: # self.add_js_expression(div, sobject, expression) return div, raw_result
def _test_status_change(self): '''Test a change to a single task.''' # Clear expression cache ExpressionParser.clear_cache() transaction = Transaction.get(create=True) task = Search.get_by_search_key(self.task_sk) new_status = 'pending' task.set_value("status", new_status) task.commit() transaction.commit() time.sleep(3) cmd = DynamicUpdateCmd(last_timestamp=self.last_timestamp, updates=self.updates) Command.execute_cmd(cmd) self.last_timestamp = cmd.get_info("timestamp") updates = cmd.get_info("updates") sobject = Search.get_by_search_key(self.search_key) num_tasks = Search.eval("@COUNT(@SOBJECT(sthpw/task))", sobject) self.assertEquals(updates["001"], num_tasks) self.assertEquals(updates["002"], new_status) self.assertEquals(updates["003"], "Loading ...") self.assertEquals(updates["004"], True) self.assertEquals(updates["005"], "Loading ...") self.assertEquals(updates["006"], num_tasks)
def get_group_bottom_wdg(my, sobjects): expression = my.get_option("group_bottom") if not expression: return None # parse the expression my.vars = my.get_vars() parser = ExpressionParser() result = parser.eval(expression, sobjects=sobjects, vars=my.vars) format_str = my.kwargs.get("display_format") if format_str: from tactic.ui.widget import FormatValueWdg format_wdg = FormatValueWdg(format=format_str, value=result) result = format_wdg else: result = str(result) div = DivWdg() div.add(result) div.add_style("text-align: right") # div.add_class( "spt_%s_expr_bottom" % (my.get_name()) ) # add a listener # for sobject in sobjects: # if sobject.is_insert(): # continue # # if my.enable_eval_listener: # my.add_js_expression(div, sobject, expression) return div
def get_mail_users(my, column): # mail groups recipients = set() expr = my.notification.get_value(column, no_exception=True) if expr: sudo = Sudo() # Introduce an environment that can be reflected env = { 'sobject': my.sobject } #if expr.startswith("@"): # logins = Search.eval(expr, list=True, env_sobjects=env) #else: parts = expr.split("\n") # go through each login and evaluate each logins = [] for part in parts: if part.startswith("@") or part.startswith("{"): results = Search.eval(part, list=True, env_sobjects=env) # clear the container after each expression eval ExpressionParser.clear_cache() # these can just be login names, get the actual Logins if results: if isinstance(results[0], basestring): login_sobjs = Search.eval("@SOBJECT(sthpw/login['login','in','%s'])" %'|'.join(results), list=True) login_list = SObject.get_values(login_sobjs, 'login') for result in results: # the original result could be an email address already if result not in login_list: logins.append(result) if login_sobjs: logins.extend( login_sobjs ) else: logins.extend(results) elif part.find("@") != -1: # this is just an email address logins.append( part ) elif part: # this is a group group = LoginGroup.get_by_code(part) if group: logins.extend( group.get_logins() ) del sudo else: notification_id = my.notification.get_id() logins = GroupNotification.get_logins_by_id(notification_id) for login in logins: recipients.add(login) return recipients
def cache(self): # get the value from cache from pyasm.biz import ExpressionParser parser = ExpressionParser() logins = parser.eval("@SOBJECT(sthpw/login)") self.attrs[self.key] = logins
def cache(my): # get the value from cache from pyasm.biz import ExpressionParser parser = ExpressionParser() logins = parser.eval("@SOBJECT(sthpw/login)") my.attrs[my.key] = logins
def get_item_div(self, sobject): ''' get the item div the sobject''' top = DivWdg() top.add_style("padding: 3px 2px") top.add_class("spt_drop_item") top.add_class("SPT_DROP_ITEM") item_div = DivWdg() top.add(item_div, "item_div") item_div.add_style("text-overflow: ellipsis") item_div.add_style("white-space: nowrap") item_div.add_style("width: 80%") item_div.add_attr('title','Click to remove') item_div.add_style("display", "inline-block") item_div.add_style("vertical-align", "top") item_div.add_style("overflow", "hidden") icon_div = DivWdg() top.add(icon_div) icon = IconWdg(icon="BS_REMOVE") icon_div.add(icon) icon_div.add_behavior( { 'type': 'click_up', #'cbjs_action': '''spt.dg_table_action.sobject_drop_remove(evt,bvr)''' 'cbjs_action': '''spt.drop.sobject_drop_remove(evt,bvr)''' } ) icon.add_style("opacity: 0.3") icon_div.add_class("hand") icon_div.add_style("display", "inline-block") icon_div.add_style("vertical-align", "top") #icon_div.add_border() #self.menu.set_over(item_div, event="mousein") #self.menu.set_out(top, event="mouseleave") # set this as the place for the display value to go item_div.add_class("spt_drop_display_value") add_icon = True ExpressionParser.clear_cache() if sobject: if add_icon: self._add_icon(sobject, item_div) if self.display_expr: display_value = Search.eval(self.display_expr, sobjects = sobject, single=True) else: display_value = sobject.get_display_value() if isinstance(display_value, list): display_value = display_value[0] item_div.add( display_value ) self.values.append( SearchKey.get_by_sobject(sobject) ) return top
def get_message(my): search_type_obj = my.sobject.get_search_type_obj() title = search_type_obj.get_title() subject = my.get_subject() notification_message = my.notification.get_value("message") if notification_message: # parse it through the expression sudo = Sudo() parser = ExpressionParser() snapshot = my.input.get('snapshot') env_sobjects = {} # turn prev_data and update_data from input into sobjects prev_data = SearchType.create("sthpw/virtual") id_col = prev_data.get_id_col() if id_col: del prev_data.data[id_col] prev_dict = my.input.get("prev_data") if prev_dict: for name, value in prev_dict.items(): if value != None: prev_data.set_value(name, value) update_data = SearchType.create("sthpw/virtual") id_col = update_data.get_id_col() if id_col: del update_data.data[id_col] update_dict = my.input.get("update_data") if update_dict: for name, value in update_dict.items(): if value != None: update_data.set_value(name, value) if snapshot: env_sobjects = { 'snapshot': snapshot } env_sobjects['prev_data'] = prev_data env_sobjects['update_data'] = update_data notification_message = parser.eval(notification_message, my.sobject, env_sobjects=env_sobjects, mode='string') del sudo return notification_message message = "%s %s" % (title, my.sobject.get_name()) message = '%s\n\nReport from transaction:\n%s\n' % (message, subject) return message
def get_item_div(my, sobject): ''' get the item div the sobject''' top = DivWdg() top.add_style("padding: 3px 2px") top.add_class("spt_drop_item") top.add_class("SPT_DROP_ITEM") item_div = DivWdg() top.add(item_div, "item_div") item_div.add_style("text-overflow: ellipsis") item_div.add_style("white-space: nowrap") item_div.add_style("width: 80%") item_div.add_attr('title', 'Click to remove') item_div.add_style("display", "inline-block") item_div.add_style("vertical-align", "top") item_div.add_style("overflow", "hidden") icon_div = DivWdg() top.add(icon_div) icon = IconWdg(icon="BS_REMOVE") icon_div.add(icon) icon_div.add_behavior({ 'type': 'click_up', #'cbjs_action': '''spt.dg_table_action.sobject_drop_remove(evt,bvr)''' 'cbjs_action': '''spt.drop.sobject_drop_remove(evt,bvr)''' }) icon.add_style("opacity: 0.3") icon_div.add_class("hand") icon_div.add_style("display", "inline-block") icon_div.add_style("vertical-align", "top") #icon_div.add_border() #my.menu.set_over(item_div, event="mousein") #my.menu.set_out(top, event="mouseleave") # set this as the place for the display value to go item_div.add_class("spt_drop_display_value") add_icon = True ExpressionParser.clear_cache() if sobject: if add_icon: my._add_icon(sobject, item_div) if my.display_expr: display_value = Search.eval(my.display_expr, sobjects=sobject, single=True) else: display_value = sobject.get_display_value() if isinstance(display_value, list): display_value = display_value[0] item_div.add(display_value) my.values.append(SearchKey.get_by_sobject(sobject)) return top
def get_message(my): search_type_obj = my.sobject.get_search_type_obj() title = search_type_obj.get_title() subject = my.get_subject() notification_message = my.notification.get_value("message") if notification_message: # parse it through the expression sudo = Sudo() parser = ExpressionParser() snapshot = my.input.get('snapshot') env_sobjects = {} # turn prev_data and update_data from input into sobjects prev_data = SearchType.create("sthpw/virtual") id_col = prev_data.get_id_col() if id_col: del prev_data.data[id_col] prev_dict = my.input.get("prev_data") if prev_dict: for name, value in prev_dict.items(): if value != None: prev_data.set_value(name, value) update_data = SearchType.create("sthpw/virtual") id_col = update_data.get_id_col() if id_col: del update_data.data[id_col] update_dict = my.input.get("update_data") if update_dict: for name, value in update_dict.items(): if value != None: update_data.set_value(name, value) if snapshot: env_sobjects = {'snapshot': snapshot} env_sobjects['prev_data'] = prev_data env_sobjects['update_data'] = update_data notification_message = parser.eval(notification_message, my.sobject, env_sobjects=env_sobjects, mode='string') del sudo return notification_message message = "%s %s" % (title, my.sobject.get_name()) message = '%s\n\nReport from transaction:\n%s\n' % (message, subject) return message
def get_subject(my): subject = my.notification.get_value("subject",no_exception=True) if subject: # parse it through the expression sudo = Sudo() parser = ExpressionParser() subject = parser.eval(subject, my.sobject, mode='string') del sudo else: subject = '%s - %s' %(my.sobject.get_update_description(), my.command.get_description()) return subject
def get_subject(self): subject = self.notification.get_value("subject",no_exception=True) if subject: # parse it through the expression sudo = Sudo() parser = ExpressionParser() subject = parser.eval(subject, self.sobject, mode='string') del sudo else: subject = '%s - %s' %(self.sobject.get_update_description(), self.command.get_description()) return subject
def get_display(my): filter_data = FilterData.get_from_cgi() values = filter_data.get_values("custom", "year") year = 0 for value in values: if value: try: year = int(value) except: pass if not year: date = Date() year = int(date.get_year()) sobject = my.get_current_sobject() id = sobject.get_id() column = my.get_option("column") month = int( my.get_option('month') ) end_year = year end_month = month + 1 if end_month > 12: end_month = 1 end_year += 1 search_type = 'MMS/personal_time_log' if year: search = Search(search_type) search.add_filter('login_id', id) search.add_filter('work_performed_date', '%s-%0.2d-01' % (year,month), '>') search.add_filter('work_performed_date', '%s-%0.2d-01' % (end_year,end_month), '<') sobjects = search.get_sobjects() else: sobjects = [] if sobjects: parser = ExpressionParser() sum = parser.eval("@SUM(%s.%s)" % (search_type,column),sobjects=sobjects) else: sum = 0 div = DivWdg() div.add(sum) return div
def get_display(self): filter_data = FilterData.get_from_cgi() values = filter_data.get_values("custom", "year") year = 0 for value in values: if value: try: year = int(value) except: pass if not year: date = Date() year = int(date.get_year()) sobject = self.get_current_sobject() id = sobject.get_id() column = self.get_option("column") month = int(self.get_option('month')) end_year = year end_month = month + 1 if end_month > 12: end_month = 1 end_year += 1 search_type = 'MMS/personal_time_log' if year: search = Search(search_type) search.add_filter('login_id', id) search.add_filter('work_performed_date', '%s-%0.2d-01' % (year, month), '>') search.add_filter('work_performed_date', '%s-%0.2d-01' % (end_year, end_month), '<') sobjects = search.get_sobjects() else: sobjects = [] if sobjects: parser = ExpressionParser() sum = parser.eval("@SUM(%s.%s)" % (search_type, column), sobjects=sobjects) else: sum = 0 div = DivWdg() div.add(sum) return div
def get_display(my): sobject = my.get_current_sobject() expression = my.get_option("expression") parser = ExpressionParser() value = parser.eval(expression, sobject) div = DivWdg() div.add_style("text-align: center") if value == False: div.add(IconWdg("XXX", IconWdg.DOT_GREEN)) else: div.add(IconWdg("YYY", IconWdg.DOT_RED)) return div
def get_display(my): sobject = my.get_current_sobject() expression = my.get_option("expression") parser = ExpressionParser() value = parser.eval(expression, sobject) div = DivWdg() div.add_style("text-align: center") if value == False: div.add( IconWdg("XXX", IconWdg.DOT_GREEN) ) else: div.add( IconWdg("YYY", IconWdg.DOT_RED) ) return div
def get_message(my): search_type_obj = my.sobject.get_search_type_obj() title = search_type_obj.get_title() subject = my.get_subject() notification_message = my.notification.get_value("message") if notification_message: # parse it through the expression sudo = Sudo() parser = ExpressionParser() notification_message = parser.eval(notification_message, my.sobject, mode='string') del sudo return notification_message message = "%s %s" % (title, my.sobject.get_name()) message = '%s\n\nReport from transaction:\n%s\n' % (message, subject) return message
def get_bottom_wdg(my): my.init_kwargs() sobjects = my.sobjects # ignore the first 2 (edit and insert) if it's on the old TableLayoutWdg if my.get_layout_wdg().get_layout_version() == '1': sobjects = sobjects[2:] if not sobjects: return None expression = my.get_option("bottom") if not expression: return None # parse the expression my.vars = my.get_vars() parser = ExpressionParser() result = parser.eval(expression, sobjects=sobjects, vars=my.vars) format_str = my.kwargs.get("display_format") if format_str: from tactic.ui.widget import FormatValueWdg format_wdg = FormatValueWdg(format=format_str, value=result) result = format_wdg else: result = str(result) div = DivWdg() div.add(result) div.add_style("text-align: right") div.add_class( "spt_%s_expr_bottom" % (my.get_name()) ) # add a listener for sobject in sobjects: if sobject.is_insert(): continue if my.enable_eval_listener: my.add_js_expression(div, sobject, expression) return div
def get_item_div(my, sobject): ''' get the item div the sobject''' top = DivWdg() top.add_attr('title', 'Click to remove') # FIXME: put this here for now top.add_behavior({ 'type': 'click_up', #'cbjs_action': '''spt.dg_table_action.sobject_drop_remove(evt,bvr)''' 'cbjs_action': '''spt.drop.sobject_drop_remove(evt,bvr)''' }) top.add_class("spt_drop_item") top.add_class("SPT_DROP_ITEM") item_div = DivWdg() item_div.add_class("hand") item_div.add_style("float: clear") top.add(item_div, "item_div") #my.menu.set_over(item_div, event="mousein") #my.menu.set_out(top, event="mouseleave") # set this as the place for the display value to go item_div.add_class("spt_drop_display_value") add_icon = True ExpressionParser.clear_cache() if sobject: if add_icon: my._add_icon(sobject, item_div) if my.display_expr: display_value = Search.eval(my.display_expr, sobjects=sobject, single=True) else: display_value = sobject.get_display_value() if isinstance(display_value, list): display_value = display_value[0] item_div.add(display_value) my.values.append(SearchKey.get_by_sobject(sobject)) return top
def get_bottom_wdg(self): self.init_kwargs() sobjects = self.sobjects # ignore the first 2 (edit and insert) if it's on the old TableLayoutWdg if self.get_layout_wdg().get_layout_version() == '1': sobjects = sobjects[2:] if not sobjects: return None expression = self.get_option("bottom") if not expression: return None # parse the expression self.vars = self.get_vars() parser = ExpressionParser() result = parser.eval(expression, sobjects=sobjects, vars=self.vars) format_str = self.kwargs.get("display_format") if format_str: from tactic.ui.widget import FormatValueWdg format_wdg = FormatValueWdg(format=format_str, value=result) result = format_wdg else: result = str(result) div = DivWdg() div.add(result) div.add_style("text-align: right") div.add_class("spt_%s_expr_bottom" % (self.get_name())) # add a listener for sobject in sobjects: if sobject.is_insert(): continue if self.enable_eval_listener: self.add_js_expression(div, sobject, expression) return div
def get_item_div(my, sobject): ''' get the item div the sobject''' top = DivWdg() top.add_style("padding: 3px 2px") top.add_attr('title','Click to remove') # FIXME: put this here for now top.add_behavior( { 'type': 'click_up', #'cbjs_action': '''spt.dg_table_action.sobject_drop_remove(evt,bvr)''' 'cbjs_action': '''spt.drop.sobject_drop_remove(evt,bvr)''' } ) top.add_class("spt_drop_item") top.add_class("SPT_DROP_ITEM") item_div = DivWdg() item_div.add_class("hand") item_div.add_style("float: clear") top.add(item_div, "item_div") #my.menu.set_over(item_div, event="mousein") #my.menu.set_out(top, event="mouseleave") # set this as the place for the display value to go item_div.add_class("spt_drop_display_value") add_icon = True ExpressionParser.clear_cache() if sobject: if add_icon: my._add_icon(sobject, item_div) if my.display_expr: display_value = Search.eval(my.display_expr, sobjects = sobject, single=True) else: display_value = sobject.get_display_value() if isinstance(display_value, list): display_value = display_value[0] item_div.add( display_value ) my.values.append( SearchKey.get_by_sobject(sobject) ) return top
def get_display(my): my.sobject = my.get_current_sobject() if not my.sobject: my.sobject = my.get_sobject_from_kwargs() if my.sobject and my.sobject.is_insert(): return DivWdg() if my.sobject: my.search_key = SearchKey.get_by_sobject(my.sobject) my.kwargs['search_key'] = my.search_key else: my.search_key = my.kwargs.get('search_key') html = my.kwargs.get('html') if not html: html = "" # DEPRECATED my.state = my.kwargs.get("state") my.state = BaseRefreshWdg.process_state(my.state) if not my.state: my.state = my.kwargs my.state['search_key'] = my.search_key my.view = my.kwargs.get('view') my.view = my.view.replace("/", ".") my.view_folder = "" if my.view.startswith("."): my.view_folder = my.kwargs.get("__view_folder__") if my.view_folder: my.view = "%s%s" % (my.view_folder, my.view) parts = my.view.split(".") my.view_folder = ".".join(parts[:-1]) if not my.view and not html: raise TacticException("No view defined in custom layout") # If html is not a string, then convert it? if not isinstance(html, basestring): html = str(html) my.view_attrs = {} my.category = my.kwargs.get("category") my.search_type = my.kwargs.get("search_type") my.encoding = my.kwargs.get("encoding") if not my.encoding: my.encoding = 'utf-8' my.plugin = None xml = None # if html is not provided, then get it from the config config = None if not html: if my.config != None: config = my.config else: config = my.kwargs.get("config") if not config: config = my.get_config() if not config: #div = DivWdg() #div.add("No config defined for view [%s] for custom layout" % my.view) #return div raise TacticException("No config defined for view [%s] for custom layout" % my.view) if isinstance(config, WidgetDbConfig): config_str = config.get_value("config") else: config_str = '' if config_str.startswith("<html>"): html = config_str my.def_config = None else: xml = config.get_xml() if my.def_config == None: my.def_config = my.get_def_config(xml) # get the view attributes if isinstance(config, WidgetConfigView): top_config = config.get_configs()[0] else: top_config = config view_node = top_config.get_view_node() if view_node is None: div = DivWdg("No view node found in xml. Invalid XML entry found") return div my.view_attrs = xml.get_attributes(view_node) nodes = xml.get_nodes("config/%s/html/*" % my.view) if not nodes: div = DivWdg("No definition found") return div # convert html tag to a div html = cStringIO.StringIO() for node in nodes: # unfortunately, html does not recognize <textarea/> # so we have to make sure it becomes <textarea></textarea> text = xml.to_string(node) text = text.encode('utf-8') keys = ['textarea','input'] for key in keys: p = re.compile("(<%s.*?/>)" % key) m = p.search(text) if m: for group in m.groups(): xx = group.replace("/", "") xx = "%s</%s>" % (xx, key) text = text.replace(group, xx) text = text.replace("<%s/>" % key, "<%s></%s>" % (key, key)) # add linebreaks to element tag key = 'element' # reg full tag <element><display...></element> p = re.compile(r"(<%s\b[^>]*>(?:.*?)</%s>)" % (key, key)) # short-hand tag <element/> p1 = re.compile("(</%s>|<%s.*?/>)" %(key, key)) m = p.search(text) m1 = p1.search(text) if m: for group in m.groups(): if group: text = text.replace(group, '\n%s\n'%group) if m1: for group in m1.groups(): if group: text = text.replace(group, '\n%s\n'%group) html.write(text) html = html.getvalue() my.config = config #my.def_config = config # This is unnessary? # try to get the sobject if this is in a table element widget if my.search_key: try: # this will raise an exception if it is not in a table element sobject = my.get_current_sobject() except: sobject = SearchKey.get_by_search_key(my.search_key) sobjects = [sobject] else: try: # this will raise an exception if it is not in a table element sobject = my.get_current_sobject() if sobject: sobjects = [sobject] else: sobjects = [] except: sobject = my.sobjects my.layout = my.get_layout_wdg() # preprocess using mako include_mako = my.kwargs.get("include_mako") if not include_mako: include_mako = my.view_attrs.get("include_mako") if xml: mako_node = xml.get_node("config/%s/mako" % my.view) if mako_node is not None: mako_str = xml.get_node_value(mako_node) html = "<%%\n%s\n%%>\n%s" % (mako_str, html) from pyasm.web import Palette num_palettes = Palette.num_palettes() #if include_mako in ['true', True]: if include_mako not in ['false', False]: html = html.replace("<", "<") html = html.replace(">", ">") html = my.process_mako(html) # preparse out expressions # use relative expressions - [expr]xxx[/expr] p = re.compile('\[expr\](.*?)\[\/expr\]') parser = ExpressionParser() matches = p.finditer(html) for m in matches: full_expr = m.group() expr = m.groups()[0] result = parser.eval(expr, sobjects, single=True, state=my.state) if isinstance(result, basestring): result = Common.process_unicode_string(result) else: result = str(result) html = html.replace(full_expr, result ) # use absolute expressions - [expr]xxx[/expr] p = re.compile('\[abs_expr\](.*?)\[\/abs_expr\]') parser = ExpressionParser() matches = p.finditer(html) for m in matches: full_expr = m.group() expr = m.groups()[0] result = parser.eval(expr, single=True) if isinstance(result, basestring): result = Common.process_unicode_string(result) else: result = str(result) html = html.replace(full_expr, result ) # need a top widget that can be used to refresh top = my.top my.set_as_panel(top) top.add_class("spt_custom_top") ignore_events = my.kwargs.get("ignore_events") in ['true', True] if ignore_events: top.add_style("pointer-events: none") # create the content div content = DivWdg() content.add_class("spt_custom_content") content.add_style("position: relative") if ignore_events: content.add_style("pointer-events: none") top.add(content) my.content = content is_test = Container.get("CustomLayout::is_test") if not is_test: is_test = my.kwargs.get("is_test") in [True, 'true'] if is_test: Container.put("CustomLayout::is_test", True) my.handle_is_test(content) html = my.replace_elements(html) content.add(html) if xml: my.add_behaviors(content, xml) # remove all the extra palettes created while True: extra_palettes = Palette.num_palettes() - num_palettes if extra_palettes > 0: Palette.pop_palette() else: break if my.kwargs.get("is_top") in ['true', True]: return html elif my.kwargs.get("is_refresh"): return content else: return top
def _get_result(self, sobject, expression): '''get the result of the expression''' element_name = self.get_name() use_cache = self.kwargs.get("use_cache") if use_cache == "true": try: return sobject.get_value(element_name) except Exception as e: print "Error: ", e.message if type(sobject) != types.ListType: if sobject.is_insert(): return '' self.vars = { 'ELEMENT_NAME': element_name, 'ELEMENT': element_name, 'SOBJECT_ID': sobject.get_id(), 'SOBJECT_CODE': sobject.get_code(), } return_type = self.kwargs.get("return") if return_type == 'single': single = True list = False elif return_type == 'list': single = False list = True else: single = True list = False # if this expression is an absolute expression, then don't bother # with the sobject expression_mode = self.get_option('expression_mode') if expression_mode == 'absolute': sobject = None calc_mode = self.get_option("calc_mode") if not calc_mode: calc_mode = 'slow' #calc_mode = 'fast' # parse the expression parser = ExpressionParser() if calc_mode == 'fast': if self.cache_results == None: self.cache_results = parser.eval(expression, self.sobjects, vars=self.vars, dictionary=True, show_retired=self.show_retired) if isinstance(self.cache_results, basestring): if self.cache_results: self.cache_results = eval(self.cache_results) else: self.cache_results = {} search_key = sobject.get_search_key() result = self.cache_results.get(search_key) if single: if result and len(result): result = result[0] else: result = '' else: result = parser.eval(expression, sobject, vars=self.vars, single=single, list=list, show_retired=self.show_retired) # FIXME: don't know how to do this any other way try: if not list: result = result.get_display_value() except AttributeError, e: pass
def process_data_gather(my, search_key, gather_specs, layout_html): sobject = Search.get_by_search_key(search_key) for label, info in gather_specs.iteritems(): if label == "@": subs_list = info.get("element_subs") for sub in subs_list: value = sobject.get_value(sub) if not value: value = " " substitution_tag = "${@.%s}" % sub layout_html = layout_html.replace(substitution_tag, "%s" % value) elif info.get("type") == "sobject": expr = info.get("expr") expr_vars_list = info.get("expr_vars") if expr_vars_list: for e_var in expr_vars_list: bits = e_var.split("=") var_name = bits[0] value = sobject.get_value(bits[1].replace("@.", "")) expr = expr.replace(var_name, "%s" % value) parser = ExpressionParser() result = parser.eval(expr) if result: if type(result) == types.ListType: other_sobject = result[0] else: other_sobject = result subs_list = info.get("element_subs") for sub in subs_list: src_col = sub dst_col = sub if "#" in sub: sub_bits = sub.split("#") src_col = sub_bits[0] dst_col = sub_bits[1] value = other_sobject.get_value(src_col) if not value: value = " " if "_date" in dst_col: value = value.split(" ")[0] if "_time" in dst_col: time_bits = value.split(" ")[1].split(":") value = "%s:%s" % (time_bits[0], time_bits[1]) substitution_tag = "${%s.%s}" % (label, dst_col) layout_html = layout_html.replace( substitution_tag, "%s" % value) elif info.get("type") == "gather_list_class": import_stmt = "%s as GatherClass" % info.get("import_stmt") exec import_stmt gc = GatherClass(sobject) item_list = gc.get_items() subs_list = info.get("element_subs") for c, item in enumerate(item_list): for sub in subs_list: substitution_tag = "${%s[%s].%s}" % (label, c, sub) layout_html = layout_html.replace( substitution_tag, "%s" % item[sub]) max_id = info.get("max_id") if max_id > (len(item_list) - 1): for c in range(len(item_list), max_id + 1): for sub in subs_list: substitution_tag = "${%s[%s].%s}" % (label, c, sub) layout_html = layout_html.replace( substitution_tag, " ") elif info.get("type") == "value": parser = ExpressionParser() value = parser.eval(info.get("expr"), sobject) if not value: value = " " layout_html = layout_html.replace("${%s}" % label, "%s" % value) return layout_html
def alter_search(my, search): if my.is_admin_flag: return True group = "search_filter" search_type = search.get_base_search_type() my.alter_search_type_search(search) # qualify the key with a project_code #project_code = "*" #key = "%s?project=%s" % (key, project_code) rules = my.groups.get(group) if not rules: return from pyasm.biz import ExpressionParser parser = ExpressionParser() current_project = None for rule in rules.values(): access, dct = rule """ # FIXME: hacky: break the encoding done earlier parts = rule.split("||") data = parts[0] data = data.replace("?project=*", "") rule = eval(data) """ rule = dct rule_search_type = rule.get('search_type') if not rule_search_type: print "No [search_type] defined in security rule" continue # search types must match if rule_search_type != search_type: continue column = rule.get('column') value = rule.get('value') project = rule.get('project') # to avoid infinite recursion, get the project here if not current_project: from pyasm.biz import Project current_project = Project.get_project_code() if project and project not in ['*', current_project]: continue # If a relationship is set, then use that # FIXME: this is not very clear how to procede. related = rule.get('related') #if search_type == 'MMS/job': # related = "@SOBJECT(MMS/request)" sudo = Sudo() if related: sobjects = parser.eval(related) search.add_relationship_filters(sobjects) del sudo return # interpret the value # since the expression runs float(), we want to avoid that a number 5 being converted to 5.0 # if we can't find @ or $ if value.find('@') != -1 or value.find('$') != -1: values = parser.eval(value, list=True) else: values = [value] op = rule.get('op') # TODO: made this work with search.add_op_filters() with the expression parser instead of this # simpler implementation if len(values) == 1: if not op: op = '=' quoted = True # special case for NULL if values[0] == 'NULL': quoted = False if op in ['not in', '!=']: search.add_op('begin') search.add_filter(column, values[0], op=op, quoted=quoted) search.add_filter(column, None) search.add_op('or') else: search.add_filter(column, values[0], op=op, quoted=quoted) elif len(values) > 1: if not op: op = 'in' if op in ['not in', '!=']: search.add_op('begin') search.add_filter(column, values, op=op) search.add_filter(column, None) search.add_op('or') else: search.add_filters(column, values, op=op) del sudo
def process_data_gather( self, search_key, gather_specs, layout_html ): sobject = Search.get_by_search_key( search_key ) for label,info in gather_specs.iteritems(): if label == "@": subs_list = info.get("element_subs") for sub in subs_list: value = sobject.get_value( sub ) if not value: value = " " substitution_tag = "${@.%s}" % sub layout_html = layout_html.replace( substitution_tag, "%s" % value ) elif info.get("type") == "sobject": expr = info.get("expr") expr_vars_list = info.get("expr_vars") if expr_vars_list: for e_var in expr_vars_list: bits = e_var.split("=") var_name = bits[0] value = sobject.get_value( bits[1].replace("@.","") ) expr = expr.replace( var_name, "%s" % value ) parser = ExpressionParser() result = parser.eval( expr ) if result: if type(result) == types.ListType: other_sobject = result[0] else: other_sobject = result subs_list = info.get("element_subs") for sub in subs_list: src_col = sub dst_col = sub if "#" in sub: sub_bits = sub.split("#") src_col = sub_bits[0] dst_col = sub_bits[1] value = other_sobject.get_value( src_col ) if not value: value = " " if "_date" in dst_col: value = value.split(" ")[0] if "_time" in dst_col: time_bits = value.split(" ")[1].split(":") value = "%s:%s" % (time_bits[0], time_bits[1]) substitution_tag = "${%s.%s}" % (label, dst_col ) layout_html = layout_html.replace( substitution_tag, "%s" % value ) elif info.get("type") == "gather_list_class": import_stmt = "%s as GatherClass" % info.get("import_stmt") exec import_stmt gc = GatherClass( sobject ) item_list = gc.get_items() subs_list = info.get("element_subs") for c, item in enumerate(item_list): for sub in subs_list: substitution_tag = "${%s[%s].%s}" % (label, c, sub) layout_html = layout_html.replace( substitution_tag, "%s" % item[ sub ] ) max_id = info.get("max_id") if max_id > (len(item_list) - 1): for c in range(len(item_list),max_id+1): for sub in subs_list: substitution_tag = "${%s[%s].%s}" % (label, c, sub) layout_html = layout_html.replace( substitution_tag, " " ) elif info.get("type") == "value": parser = ExpressionParser() value = parser.eval( info.get("expr"), sobject ) if not value: value = " " layout_html = layout_html.replace( "${%s}" % label, "%s" % value ) return layout_html
def get_display(self): sobject = self.get_current_sobject() search_key = SearchKey.build_by_sobject(sobject) display = DivWdg() display.add_style("position: relative") display.add_class("spt_button_top") display.add_style("width: 26px") display.add_style("margin-left: auto") display.add_style("margin-right: auto") BASE = '/context/themes2/default/' over_div = DivWdg() display.add(over_div) over_div.add_class("spt_button_over") over_img = "<img src='%s/MainButton_over.png'/>" % BASE over_div.add(over_img) over_div.add_style("position: absolute") over_div.add_style("top: -9px") over_div.add_style("left: 0px") over_div.add_style("display: none") click_div = DivWdg() display.add(click_div) click_div.add_class("spt_button_click") click_img = "<img src='%s/MainButton_click.png'/>" % BASE click_div.add(click_img) click_div.add_style("position: absolute") click_div.add_style("top: -9px") click_div.add_style("left: 0px") click_div.add_style("display: none") if self.get_option('align') == 'left': display.add_style("text-align: left") else: display.add_style("text-align: center") icon = self.get_option("icon") if not icon: icon = "create" icon_tip = self.get_option("icon_tip") if not icon_tip: icon_tip = self.get_option("hint") if not icon_tip: icon_tip = "" enable = self.get_option("enable") if enable: result = ExpressionParser().eval(enable, sobject) if not result: return " " if not self.script_obj and not self.script: icon_wdg = IconButtonWdg("No Script Found", IconWdg.ERROR) else: icon_link = icon.upper() icon_wdg = IconButtonWdg(icon_tip, icon=icon_link) if not sobject.is_insert(): icon_wdg.add_class("hand") #icon_wdg.add_behavior(self.behavior) icon_wdg.add_class("spt_button_%s" % self.name) icon_div = DivWdg() icon_div.add(icon_wdg) icon_div.add_style("position: absolute") icon_div.add_style("top: 2px") icon_div.add_style("left: 5px") display.add(icon_div) hit_wdg = icon_div hit_wdg.add_class("spt_button_hit") if sobject.is_insert(): hit_wdg.add_style("opacity: 0.4") else: hit_wdg.add_class("spt_button_hit_wdg") display.add_style("height: 18px") display.add_style("min-width: 21px") #display.add_style("overflow: hidden") display.add_style("margin-top: 0px") expression = self.kwargs.get('expression') if expression: value = Search.eval(expression, sobject, single=True) if value: badge = DivWdg() badge.add_style("position: absolute") badge.add_style("right: -30px") badge.add_style("top: -2px") badge.add_style("margin: 4px 3px 3px 6px") badge.add_style("opacity: 0.5") badge.add_style("font-size: 0.7em") badge.add_class("badge") badge.add(value) display.add(badge) display.add_style("position: relative") #return top return display
class ExpressionElementWdg(TypeTableElementWdg): '''General purpose element widget for expressions''' ARGS_KEYS = { 'expression': { 'description': 'Expression to evaluate the widget', 'type': 'TextAreaWdg', 'order': 1, 'category': 'Options' }, 'display_expression': { 'description': 'Expression for display purposes', 'type': 'TextAreaWdg', 'order': 2, 'category': 'Options' }, 'display_format': { 'description': 'Predefined format for display', 'type': 'TextWdg', 'order': 3, 'category': 'Options' }, 'inline_styles': 'Styles to add to the DIV generated that contains the result of the expression', 'return': { 'descripton': 'Determines what the expression return type should be', 'type': 'SelectWdg', 'values': 'single|list' }, 'bottom': { 'description': 'Expression to calculate the bottom row of the table', 'type': 'TextAreaWdg', }, 'group_bottom': { 'description': 'Expression to calculate the bottom of a group', 'type': 'TextAreaWdg', }, 'mode': { 'description': 'Display mode for this widget', 'type': 'SelectWdg', 'values': 'value|check|boolean', 'order': 3 }, 'expression_mode': { 'description': 'If absolute mode is selected, it does not relate to the current SObject', 'type': 'SelectWdg', 'values': 'default|absolute', 'order': 4 }, 'calc_mode': { 'description': '(ALPHA) fast|slow - fast uses new calculation mode. Only @SUM, @COUNT, @SOBJECT and @GET are current supported', 'type': 'SelectWdg', 'values': 'slow|fast', 'order': 5 }, 'show_retired': { 'description': 'true|false - true shows all the retired entries during the expression evaluation', 'type': 'SelectWdg', 'values': 'true|false', 'category': 'Options', 'order': 6 }, 'enable_eval_listener': { 'description': '''Currently javascript expression evaluation is not fully baked, so only use the client side evaluation listener when needed and NOT by default''', 'category': 'internal', }, 'use_cache': { 'description': 'Determines whether or not to use the cached value. Gets value from column with the same name as the element', 'type': 'SelectWdg', 'values': 'true|false', 'order': 0, 'category': 'Cache' }, 'order_by': { 'description': 'Turn on Order by', 'type': 'TextWdg', 'order': 7, 'category': 'Options' }, 'group_by': { 'description': 'Turn on Group by', 'type': 'SelectWdg', 'values': 'true|false', 'order': 8, 'category': 'Options' }, 'group_by_time': { 'description': 'Turn on Group by', 'type': 'SelectWdg', 'values': 'true|false', 'order': 9, 'category': 'Options' }, 'justify': { 'description': 'Result justification', 'type': 'SelectWdg', 'values': 'default|left|right|center', 'order': 91, 'category': 'Options' } } def init(my): my.td = None my.expression = None my.alt_expression = None my.alt_result = None my.cache_results = None def preprocess(my): order_by = my.get_option("order_by") # for backward compatibility when order_by used to be true/false if not order_by or order_by == 'true': expression = my.get_option("expression") if expression.startswith("@GET(") and expression.endswith( ")") and expression.count("@") == 1: template = expression.lstrip("@GET(") template = template.rstrip(")") # remove white spaces template = template.strip() # if it's a simple local sType expression e.g. @GET(.id), strip the . if template.startswith("."): template = template.lstrip('.') my.set_option("order_by", template) def get_required_columns(my): '''method to get the require columns for this''' return [] def get_header_option_wdg(my): return if my.kwargs.get("use_cache2") not in ['true', True]: return div = DivWdg() div.add("Last Calculated: 5 days ago<br/><hr/>") div.add("Recalculate") div.add_class("hand") #from tactic.ui.widget import ActionButtonWdg #button = ActionButtonWdg(title="Recalculate") #div.add(button) div.add_behavior({ 'type': 'click_up', 'cbjs_action': ''' var table = bvr.src_el.getParent(".spt_table"); //var search_keys = spt.dg_table.get_search_keys(); var search_keys = spt.dg_table.get_selected_search_keys(table); if (search_keys.length == 0) { spt.alert("No rows selected"); return; } var header = bvr.src_el.getParent(".spt_table_th"); var element_name = header.getAttribute("spt_element_name"); spt.app_busy.show("Recalculating ..."); var kwargs = { element_name: element_name, search_keys: search_keys, } spt.app_busy.show("Recalculating ..."); var server = TacticServerStub.get(); var class_name = 'tactic.ui.table.ExpressionRecalculateCmd'; server.execute_cmd(class_name, kwargs); spt.app_busy.hide("Recalculating ..."); ''' }) return div def is_sortable(my): use_cache = my.get_option("use_cache") in ['true', True] if use_cache: return True order_by = my.get_option("order_by") # false is the word to prevent the auto-adoption (preprocess) of the expression to order-by if order_by and order_by != 'false': parts = order_by.split(".") if "connect" in parts: return False return True else: return False def is_groupable(my): use_cache = my.get_option("use_cache") in ['true', True] if use_cache: return True group_by = my.get_option("group_by") if group_by: return True else: return False def is_time_groupable(my): group_by = my.get_option("group_by_time") if group_by: return True else: return False def get_vars(my): # create variables element_name = my.get_name() my.vars = {'ELEMENT_NAME': element_name} # get info from search critiera # FIXME: this should be formalized search_vars = Container.get("Message:search_vars") if search_vars: for name, value in search_vars.items(): my.vars[name] = value return my.vars def get_input_by_arg_key(my, key): if key == 'expression': input = TextAreaWdg("option_expression") else: input = TextWdg("value") return input get_input_by_arg_key = classmethod(get_input_by_arg_key) def handle_td(my, td): if my.alt_result: td.add_attr("spt_input_value", my.alt_result) elif my.alt_result: td.add_attr("spt_input_value", my.value) super(ExpressionElementWdg, my).handle_td(td) def is_editable(my): return 'optional' def _get_result(my, sobject, expression): '''get the result of the expression''' element_name = my.get_name() use_cache = my.kwargs.get("use_cache") if use_cache == "true": try: return sobject.get_value(element_name) except Exception, e: print "Error: ", e.message if type(sobject) != types.ListType: if sobject.is_insert(): return '' my.vars = { 'ELEMENT_NAME': element_name, 'ELEMENT': element_name, 'SOBJECT_ID': sobject.get_id(), 'SOBJECT_CODE': sobject.get_code(), } return_type = my.kwargs.get("return") if return_type == 'single': single = True list = False elif return_type == 'list': single = False list = True else: single = True list = False # if this expression is an absolute expression, then don't bother # with the sobject expression_mode = my.get_option('expression_mode') if expression_mode == 'absolute': sobject = None calc_mode = my.get_option("calc_mode") if not calc_mode: calc_mode = 'slow' #calc_mode = 'fast' # parse the expression parser = ExpressionParser() if calc_mode == 'fast': if my.cache_results == None: my.cache_results = parser.eval(expression, my.sobjects, vars=my.vars, dictionary=True, show_retired=my.show_retired) if isinstance(my.cache_results, basestring): if my.cache_results: my.cache_results = eval(my.cache_results) else: my.cache_results = {} search_key = sobject.get_search_key() result = my.cache_results.get(search_key) if single: if result and len(result): result = result[0] else: result = '' else: result = parser.eval(expression, sobject, vars=my.vars, single=single, list=list, show_retired=my.show_retired) # FIXME: don't know how to do this any other way try: if not list: result = result.get_display_value() except AttributeError, e: pass
def alter_search(self, search): if self.is_admin_flag: return True group = "search_filter" search_type = search.get_base_search_type() self.alter_search_type_search(search) rules = self.groups.get(group) if not rules: return from pyasm.biz import ExpressionParser parser = ExpressionParser() current_project = None # preprocess to get a list of rule that will apply rules_dict = {} for rule_item in rules.values(): access, dct = rule_item rule = dct rule_search_type = rule.get('search_type') if not rule_search_type: print "No [search_type] defined in security rule" continue # search types must match if rule_search_type != search_type: continue project = rule.get('project') # to avoid infinite recursion, get the project here if not current_project: from pyasm.biz import Project current_project = Project.get_project_code() if project and project not in ['*', current_project]: continue column = rule.get('column') rules_list = rules_dict.get(column) if rules_list == None: rules_list = [] rules_dict[column] = rules_list rules_list.append(rule) for column, rules_list in rules_dict.items(): if len(rules_list) > 1: search.add_op("begin") for rule in rules_list: column = rule.get('column') value = rule.get('value') # If a relationship is set, then use that related = rule.get('related') sudo = Sudo() if related: sobjects = parser.eval(related) search.add_relationship_filters(sobjects) del sudo return # interpret the value # since the expression runs float(), we want to avoid that a number 5 being converted to 5.0 # if we can't find @ or $ if value.find('@') != -1 or value.find('$') != -1: values = parser.eval(value, list=True) elif value.find("|") == -1: values = value.split("|") else: values = [value] op = rule.get('op') # TODO: made this work with search.add_op_filters() with the expression parser instead of this # simpler implementation if len(values) == 1: if not op: op = '=' quoted = True # special case for NULL if values[0] == 'NULL': quoted = False if op in ['not in', '!=']: search.add_op('begin') search.add_filter(column, values[0], op=op, quoted=quoted) search.add_filter(column, None) search.add_op('or') else: search.add_filter(column, values[0], op=op, quoted=quoted) elif len(values) > 1: if not op: op = 'in' if op in ['not in', '!=']: search.add_op('begin') search.add_filter(column, values, op=op) search.add_filter(column, None) search.add_op('or') else: search.add_filters(column, values, op=op) del sudo if len(rules_list) > 1: search.add_op("or")
def handle_sobject(my, main_sobject, caller, notification, input): # TODO: deal with parents later parent = main_sobject.get_parent() snapshot = input.get('snapshot') env_sobjects = {} if snapshot: env_sobjects = {'snapshot': snapshot} # get the rules from the database rules_xml = notification.get_xml_value("rules") rule_nodes = rules_xml.get_nodes("rules/rule") is_skipped = True parser = ExpressionParser() # process the rules for rule_node in rule_nodes: rule = [] group_type = Xml.get_attribute(rule_node, "group") rule_key = Xml.get_attribute(rule_node, 'key') rule_value = Xml.get_attribute(rule_node, 'value') compare = Xml.get_attribute(rule_node, 'compare') # evaluate the expression if it exists expression = Xml.get_node_value(rule_node) if expression: result = parser.eval(expression, main_sobject, env_sobjects=env_sobjects) if not result: break else: continue # DEPRECATED: likely the expression complete replaces this # parse the rule if group_type == "sobject": if not my._process_sobject(main_sobject, rule_key, compare): break value = main_sobject.get_value(rule_key, no_exception=True) elif group_type == "parent": if not parent or not my._process_sobject( parent, rule_key, compare): break value = parent.get_value(rule_key, no_exception=True) else: # group_type == 'command' try: value = caller.get_info(rule_key) except: value = '' if not value: break # match the rule to the value p = re.compile(rule_value) if not p.match(value): print "... skipping: '%s' != %s" % (value, rule_value) break else: is_skipped = False # allow the handler to check for whether an email should be sent handler = my.get_email_handler(notification, main_sobject, parent, caller, input) if is_skipped or not handler.check_rule(): my.add_description( 'Notification not sent due to failure to pass the set rules. Comment out the rules for now if you are just running email test.' ) return print "sending email!!!" # if all rules are met then get the groups for this notification try: to_users = handler.get_to() cc_users = handler.get_cc() bcc_users = handler.get_bcc() subject = handler.get_subject() if len(subject) > 60: subject = subject[0:60] + " ..." message = handler.get_message() except SObjectValueException, e: raise Exception("Error in running Email handler [%s]. %s" \ %(handler.__class__.__name__, e.__str__()))
def handle_sobject(my, main_sobject, caller, notification, input): # TODO: deal with parents later parent = main_sobject.get_parent() snapshot = input.get('snapshot') env_sobjects = {} if snapshot: env_sobjects = { 'snapshot': snapshot } # get the rules from the database rules_xml = notification.get_xml_value("rules") rule_nodes = rules_xml.get_nodes("rules/rule") is_skipped = True parser = ExpressionParser() # process the rules for rule_node in rule_nodes: rule = [] group_type = Xml.get_attribute( rule_node, "group" ) rule_key = Xml.get_attribute(rule_node, 'key') rule_value = Xml.get_attribute(rule_node, 'value') compare = Xml.get_attribute(rule_node, 'compare') # evaluate the expression if it exists expression = Xml.get_node_value(rule_node) if expression: result = parser.eval(expression, main_sobject, env_sobjects=env_sobjects) if not result: break else: continue # DEPRECATED: likely the expression complete replaces this # parse the rule if group_type == "sobject": if not my._process_sobject(main_sobject, rule_key, compare): break value = main_sobject.get_value(rule_key, no_exception=True ) elif group_type == "parent": if not parent or not my._process_sobject(parent, rule_key, compare): break value = parent.get_value(rule_key, no_exception=True ) else: # group_type == 'command' try: value = caller.get_info(rule_key) except: value = '' if not value: break # match the rule to the value p = re.compile(rule_value) if not p.match(value): print "... skipping: '%s' != %s" % (value, rule_value) break else: is_skipped = False # allow the handler to check for whether an email should be sent handler = my.get_email_handler(notification, main_sobject, parent, caller, input) if is_skipped or not handler.check_rule(): my.add_description('Notification not sent due to failure to pass the set rules. Comment out the rules for now if you are just running email test.') return print "sending email!!!" # if all rules are met then get the groups for this notification try: to_users = handler.get_to() cc_users = handler.get_cc() bcc_users = handler.get_bcc() subject = handler.get_subject() if len(subject) > 60: subject = subject[0:60] + " ..." message = handler.get_message() except SObjectValueException, e: raise Exception("Error in running Email handler [%s]. %s" \ %(handler.__class__.__name__, e.__str__()))
def get_mail_users(my, column): # mail groups recipients = set() expr = my.notification.get_value(column, no_exception=True) if expr: sudo = Sudo() # Introduce an environment that can be reflected env = {'sobject': my.sobject} #if expr.startswith("@"): # logins = Search.eval(expr, list=True, env_sobjects=env) #else: parts = expr.split("\n") # go through each login and evaluate each logins = [] for part in parts: if part.startswith("@") or part.startswith("{"): results = Search.eval(part, list=True, env_sobjects=env) # clear the container after each expression eval ExpressionParser.clear_cache() # these can just be login names, get the actual Logins if results: if isinstance(results[0], basestring): login_sobjs = Search.eval( "@SOBJECT(sthpw/login['login','in','%s'])" % '|'.join(results), list=True) login_list = SObject.get_values( login_sobjs, 'login') for result in results: # the original result could be an email address already if result not in login_list: logins.append(result) if login_sobjs: logins.extend(login_sobjs) else: logins.extend(results) elif part.find("@") != -1: # this is just an email address logins.append(part) elif part: # this is a group group = LoginGroup.get_by_code(part) if group: logins.extend(group.get_logins()) del sudo else: notification_id = my.notification.get_id() logins = GroupNotification.get_logins_by_id(notification_id) for login in logins: recipients.add(login) return recipients
def _get_result(self, sobject, expression): '''get the result of the expression''' element_name = self.get_name() use_cache = self.kwargs.get("use_cache") if use_cache == "true": try: return sobject.get_value(element_name) except Exception as e: print "Error: ", e.message if type(sobject) != types.ListType: if sobject.is_insert(): return '' self.vars = { 'ELEMENT_NAME': element_name, 'ELEMENT': element_name, 'SOBJECT_ID': sobject.get_id(), 'SOBJECT_CODE': sobject.get_code(), } return_type = self.kwargs.get("return") if return_type == 'single': single = True list = False elif return_type == 'list': single = False list = True else: single = True list = False # if this expression is an absolute expression, then don't bother # with the sobject expression_mode = self.get_option('expression_mode') if expression_mode == 'absolute': sobject = None calc_mode = self.get_option("calc_mode") if not calc_mode: calc_mode = 'slow' #calc_mode = 'fast' # parse the expression parser = ExpressionParser() if calc_mode == 'fast': if self.cache_results == None: self.cache_results = parser.eval( expression, self.sobjects, vars=self.vars, dictionary=True, show_retired=self.show_retired) if isinstance(self.cache_results, basestring): if self.cache_results: self.cache_results = eval(self.cache_results) else: self.cache_results = {} search_key = sobject.get_search_key() result = self.cache_results.get(search_key) if single: if result and len(result): result = result[0] else: result = '' else: result = parser.eval(expression, sobject, vars=self.vars, single=single, list=list, show_retired=self.show_retired) # FIXME: don't know how to do this any other way try: if not list: result = result.get_display_value() except AttributeError, e: pass
def get_display(my): sobject = my.get_current_sobject() search_key = SearchKey.build_by_sobject(sobject) display = DivWdg() display.add_style("position: relative") display.add_class("spt_button_top") BASE = '/context/themes2/default/' over_div = DivWdg() display.add(over_div) over_div.add_class("spt_button_over") over_img = "<img src='%s/MainButton_over.png'/>" % BASE over_div.add(over_img) over_div.add_style("position: absolute") over_div.add_style("top: -9px") over_div.add_style("left: 0px") over_div.add_style("display: none") click_div = DivWdg() display.add(click_div) click_div.add_class("spt_button_click") click_img = "<img src='%s/MainButton_click.png'/>" % BASE click_div.add(click_img) click_div.add_style("position: absolute") click_div.add_style("top: -9px") click_div.add_style("left: 0px") click_div.add_style("display: none") if my.get_option('align') == 'left': display.add_style("text-align: left") else: display.add_style("text-align: center") icon = my.get_option("icon") if not icon: icon = "create" icon_tip = my.get_option("icon_tip") if not icon_tip: icon_tip = my.get_option("hint") if not icon_tip: icon_tip = "" enable = my.get_option("enable") if enable: result = ExpressionParser().eval(enable, sobject) if not result: return " " if not my.script_obj and not my.script: icon_wdg = IconButtonWdg("No Script Found", IconWdg.ERROR) else: try: icon_link = eval("IconWdg.%s" % icon.upper()) except Exception, e: print "WARNING: ", str(e) icon_link = IconWdg.ERROR icon_wdg = IconButtonWdg(icon_tip, icon_link) if not sobject.is_insert(): icon_wdg.add_class("hand") #icon_wdg.add_behavior(my.behavior) icon_wdg.add_class("spt_button_%s" % my.name)
def alter_search(my, search): if my.is_admin_flag: return True group = "search_filter" search_type = search.get_base_search_type() my.alter_search_type_search(search) rules = my.groups.get(group) if not rules: return from pyasm.biz import ExpressionParser parser = ExpressionParser() current_project = None for rule in rules.values(): access, dct = rule """ # FIXME: hacky: break the encoding done earlier parts = rule.split("||") data = parts[0] data = data.replace("?project=*", "") rule = eval(data) """ rule = dct rule_search_type = rule.get('search_type') if not rule_search_type: print "No [search_type] defined in security rule" continue # search types must match if rule_search_type != search_type: continue column = rule.get('column') value = rule.get('value') project = rule.get('project') # to avoid infinite recursion, get the project here if not current_project: from pyasm.biz import Project current_project = Project.get_project_code() if project and project not in ['*', current_project]: continue # If a relationship is set, then use that # FIXME: this is not very clear how to procede. related = rule.get('related') sudo = Sudo() if related: sobjects = parser.eval(related) search.add_relationship_filters(sobjects) del sudo return # interpret the value # since the expression runs float(), we want to avoid that a number 5 being converted to 5.0 # if we can't find @ or $ if value.find('@') != -1 or value.find('$') != -1: values = parser.eval(value, list=True) else: values = [value] op = rule.get('op') # TODO: made this work with search.add_op_filters() with the expression parser instead of this # simpler implementation if len(values) == 1: if not op: op = '=' quoted = True # special case for NULL if values[0] == 'NULL': quoted = False if op in ['not in', '!=']: search.add_op('begin') search.add_filter(column, values[0], op=op, quoted=quoted) search.add_filter(column, None) search.add_op('or') else: search.add_filter(column, values[0], op=op, quoted=quoted) elif len(values) > 1: if not op: op = 'in' if op in ['not in', '!=']: search.add_op('begin') search.add_filter(column, values, op=op) search.add_filter(column, None) search.add_op('or') else: search.add_filters(column, values, op=op) del sudo
def get_display(my): my.sobject = my.get_current_sobject() if not my.sobject: my.sobject = my.get_sobject_from_kwargs() if my.sobject and my.sobject.is_insert(): return DivWdg() if my.sobject: my.search_key = SearchKey.get_by_sobject(my.sobject) my.kwargs['search_key'] = my.search_key else: my.search_key = my.kwargs.get('search_key') html = my.kwargs.get('html') if not html: html = "" # DEPRECATED my.state = my.kwargs.get("state") my.state = BaseRefreshWdg.process_state(my.state) if not my.state: my.state = my.kwargs my.state['search_key'] = my.search_key my.view = my.kwargs.get('view') my.view = my.view.replace("/", ".") my.view_folder = "" if my.view.startswith("."): my.view_folder = my.kwargs.get("__view_folder__") if my.view_folder: my.view = "%s%s" % (my.view_folder, my.view) parts = my.view.split(".") my.view_folder = ".".join(parts[:-1]) if not my.view and not html: raise TacticException("No view defined in custom layout") # If html is not a string, then convert it? if not isinstance(html, basestring): html = str(html) my.view_attrs = {} my.category = my.kwargs.get("category") my.search_type = my.kwargs.get("search_type") my.encoding = my.kwargs.get("encoding") if not my.encoding: my.encoding = 'utf-8' my.plugin = None xml = None # if html is not provided, then get it from the config config = None if not html: if my.config != None: config = my.config else: config = my.kwargs.get("config") if not config: config = my.get_config() if not config: #div = DivWdg() #div.add("No config defined for view [%s] for custom layout" % my.view) #return div raise TacticException("No config defined for view [%s] for custom layout" % my.view) if isinstance(config, WidgetDbConfig): config_str = config.get_value("config") else: config_str = '' if config_str.startswith("<html>"): html = config_str my.def_config = None else: xml = config.get_xml() if my.def_config == None: my.def_config = my.get_def_config(xml) # get the view attributes if isinstance(config, WidgetConfigView): top_config = config.get_configs()[0] else: top_config = config view_node = top_config.get_view_node() if view_node is None: div = DivWdg("No view node found in xml. Invalid XML entry found") return div my.view_attrs = xml.get_attributes(view_node) nodes = xml.get_nodes("config/%s/html/*" % my.view) if not nodes: div = DivWdg("No definition found") return div # convert html tag to a div html = cStringIO.StringIO() for node in nodes: # unfortunately, html does not recognize <textarea/> # so we have to make sure it becomes <textarea></textarea> text = xml.to_string(node) text = text.encode('utf-8') keys = ['textarea','input'] for key in keys: p = re.compile("(<%s.*?/>)" % key) m = p.search(text) if m: for group in m.groups(): xx = group.replace("/", "") xx = "%s</%s>" % (xx, key) text = text.replace(group, xx) text = text.replace("<%s/>" % key, "<%s></%s>" % (key, key)) # add linebreaks to element tag key = 'element' # reg full tag <element><display...></element> p = re.compile(r"(<%s\b[^>]*>(?:.*?)</%s>)" % (key, key)) # short-hand tag <element/> p1 = re.compile("(</%s>|<%s.*?/>)" %(key, key)) m = p.search(text) m1 = p1.search(text) if m: for group in m.groups(): if group: text = text.replace(group, '\n%s\n'%group) if m1: for group in m1.groups(): if group: text = text.replace(group, '\n%s\n'%group) html.write(text) html = html.getvalue() my.config = config #my.def_config = config # This is unnessary? # try to get the sobject if this is in a table element widget if my.search_key: try: # this will raise an exception if it is not in a table element sobject = my.get_current_sobject() except: sobject = SearchKey.get_by_search_key(my.search_key) sobjects = [sobject] else: try: # this will raise an exception if it is not in a table element sobject = my.get_current_sobject() if sobject: sobjects = [sobject] else: sobjects = [] except: sobject = my.sobjects my.layout = my.get_layout_wdg() # preprocess using mako include_mako = my.kwargs.get("include_mako") if not include_mako: include_mako = my.view_attrs.get("include_mako") if xml: mako_node = xml.get_node("config/%s/mako" % my.view) if mako_node is not None: mako_str = xml.get_node_value(mako_node) html = "<%%\n%s\n%%>\n%s" % (mako_str, html) from pyasm.web import Palette num_palettes = Palette.num_palettes() #if include_mako in ['true', True]: if include_mako not in ['false', False]: html = html.replace("<", "<") html = html.replace(">", ">") html = my.process_mako(html) # preparse out expressions # use relative expressions - [expr]xxx[/expr] p = re.compile('\[expr\](.*?)\[\/expr\]') parser = ExpressionParser() matches = p.finditer(html) for m in matches: full_expr = m.group() expr = m.groups()[0] result = parser.eval(expr, sobjects, single=True, state=my.state) if isinstance(result, basestring): result = Common.process_unicode_string(result) else: result = str(result) html = html.replace(full_expr, result ) # use absolute expressions - [expr]xxx[/expr] p = re.compile('\[abs_expr\](.*?)\[\/abs_expr\]') parser = ExpressionParser() matches = p.finditer(html) for m in matches: full_expr = m.group() expr = m.groups()[0] result = parser.eval(expr, single=True) if isinstance(result, basestring): result = Common.process_unicode_string(result) else: result = str(result) html = html.replace(full_expr, result ) # need a top widget that can be used to refresh top = my.top my.set_as_panel(top) top.add_class("spt_custom_top") # create the content div content = DivWdg() content.add_class("spt_custom_content") content.add_style("position: relative") top.add(content) my.content = content is_test = Container.get("CustomLayout::is_test") if not is_test: is_test = my.kwargs.get("is_test") in [True, 'true'] if is_test: Container.put("CustomLayout::is_test", True) my.handle_is_test(content) html = my.replace_elements(html) content.add(html) if xml: my.add_behaviors(content, xml) # remove all the extra palettes created while True: extra_palettes = Palette.num_palettes() - num_palettes if extra_palettes > 0: Palette.pop_palette() else: break if my.kwargs.get("is_refresh"): return content else: return top