def handle_remark(self, time, remark): targetid = self.out.new_id() self.out.timestamp(time) self.out.newstate('plain', '', '', '<h3 id="%s" class="remark">%s</h3>\n' % (targetid, escape_html(remark))) self.out.toc_entry(2, escape_html(remark), targetid)
def _create_field(blk, config): if 'widget' in config or 'gui' in config: self.log.warning('ignoring "widget" or "gui" element in HTML ' 'monitor configuration') return None field = Field(self._prefix, config) field.updateKeymap(self._keymap) if field.plot and pygr: p = self._plots.get(field.plot) if not p: p = Plot(field.plotwindow, field.width, field.height) self._plots[field.plot] = p blk += p field._plotcurve = p.addcurve(field.name) elif field.picture: pic = Picture(field.picture, field.width, field.height, escape_html(field.name)) blk += pic else: # deactivate plots field.plot = None # create name label flabel = field._namelabel = Label('name', field.width, escape_html(field.name)) blk += flabel blk += u'</td></tr><tr><td>' # create value label cls = 'value' if field.istext: cls += ' istext' vlabel = field._valuelabel = Label(cls, fore='white') blk += vlabel return field
def submitIssue(self, ticket_type, is_critical, subject, description, reproduction, add_log): def wrap(text): return escape_html(text).replace('\n\n', '</p><p>'). \ replace('\n', '<br/>') full_desc = '<p>' + wrap(description) + '</p>' if reproduction: full_desc += '\n\n<p><b>Reproduction:</b></p>' + \ '<p>' + wrap(reproduction) + '</p>' if self.traceback: full_desc += '\n\n<p><b>Traceback:</b></p>\n' + \ '<pre>' + escape_html(self.traceback) + '</pre>' if add_log and self.log_excerpt: full_desc += '\n\n<p><b>Log excerpt:</b></p>\n' + \ '<pre>' + escape_html(self.log_excerpt) + '</pre>' rm = redminelib.Redmine(TRACKER_URL, key=self.apikey) issue = rm.issue.new() issue.project_id = PROJECT_ID issue.subject = subject trackers = rm.tracker.all() tracker_id = [t.id for t in trackers if t.name == ticket_type][0] issue.tracker_id = tracker_id issue.description = full_desc if is_critical: prios = rm.enumeration.filter(resource='issue_priorities') prio_id = [p.id for p in prios if p.name == 'Urgent'][0] issue.priority_id = prio_id if self.instrument != 'none': issue.custom_fields = [{'id': 1, 'value': self.instrument}] issue.save() return issue.id
def formatMessage(message): """Format message for display in the HTML logbook.""" cls = 'out' levelno = message[2] if levelno == ACTION: return '' if message[0] == 'nicos': name = '' else: name = '%-10s: ' % message[0] name = message[5] + name if levelno <= DEBUG: text = name + message[3] cls = 'debug' elif levelno <= INFO: text = name + message[3] elif levelno == INPUT: return '<span class="input">' + escape_html(message[3]) + '</span>' elif levelno <= WARNING: text = levels[levelno] + ': ' + name + message[3] cls = 'warn' else: text = '%s [%s] %s%s' % (levels[levelno], formatTime( message[1]), name, message[3]) cls = 'err' return '<span class="%s">%s</span>' % (cls, escape_html(text))
def gen_markup(self, markup): if publish_parts is None: return '<pre>' + escape_html(markup) + '</pre>' else: try: return publish_parts(markup, writer_name='html')['fragment'] except Exception: return '<pre>' + escape_html(markup) + '</pre>'
def handle_newexperiment(self, time, data): proposal, title = data targetid = self.out.new_id() if title: text = 'Experiment %s: %s' % (escape_html(proposal), escape_html(title)) else: text = 'Experiment %s' % escape_html(proposal) self.out.timestamp(time) self.out.newstate('plain', '', '', '<h1 id="%s">%s</h1>\n' % (targetid, text)) self.out.toc_entry(1, text, targetid)
def _list(cls): if cls in listed: return listed.add(cls) for name, (args, doc, fromtype, is_usermethod) in sorted(iteritems(cls.methods)): if is_usermethod and fromtype is cls: ret.append( '<tr><td><tt>%s</tt></td><td>%s</td><td>%s</td></tr>' % (escape_html(dev.name + '.' + name + args), cls.__name__, escape_html(doc))) for base in cls.__bases__: if issubclass(base, Device): _list(base)
def handle_offset(self, time, data): self.out.timestamp(time) dev, old, new = data self.out.newstate('plain', '', '', '<p class="offset"><b>Adjustment:</b> ' + escape_html('Offset of %s changed from %s to %s' % (dev, old, new)) + '</p>\n')
def handle_detectors(self, time, dlist): self.out.timestamp(time) text = 'New standard detectors: %s' % escape_html(', '.join(dlist)) targetid = self.out.new_id() self.out.toc_entry(2, text, targetid, 'detectors') self.out.newstate('plain', '', '', '<p id="%s" class="detectors">%s</p>\n' % (targetid, text))
def handle_sample(self, time, data): self.out.timestamp(time) text = 'New sample: %s' % escape_html(data) targetid = self.out.new_id() self.out.toc_entry(2, text, targetid, 'sample') self.out.newstate('plain', '', '', '<p id="%s" class="sample">%s</p>\n' % (targetid, text))
def handle_scriptend(self, time, data): self.out.timestamp(time) targetid = self.out.new_id() text = 'Script finished: %s' % escape_html(data) # self.out.toc_entry(2, text, targetid) self.out.newstate('plain', '', '', '<p id="%s" class="scriptend">%s</p>\n' % (targetid, text))
def handle_environment(self, time, dlist): self.out.timestamp(time) text = 'New standard environment: %s' % escape_html(', '.join(dlist)) targetid = self.out.new_id() self.out.toc_entry(2, text, targetid, 'environment') self.out.newstate('plain', '', '', '<p id="%s" class="environment">%s</p>\n' % (targetid, text))
def toc_entry(self, level, text, target, cls=None): html = '' if self.toc_level < level: html += '<ul class="toc">' * (level - self.toc_level) elif self.toc_level > level: html += '</ul>' * (self.toc_level - level) + '\n' html += ('<li class="toc"><a href="content.html#%s" ' 'target="content"%s>%s</a></li>\n' % ( target, cls and ' class="%s"' % cls or '', escape_html(text))) self.emit_toc(html) self.toc_level = level
def handle_entry(self, time, data): self.out.timestamp(time) if creole: emitter = creole.HtmlEmitter( creole.Parser(from_utf8(data)).parse(), self.out.new_id) data = emitter.emit() headers = emitter.headers else: data, headers = escape_html(data), [] self.out.newstate('entry', '', '', data) for level, text, targetid in headers: self.out.toc_entry(level, text, targetid)
def handle_attachment(self, time, data): if not self.logdir: return description, fpaths, names = data links = [] for fpath, name in zip(fpaths, names): fullname = path.join(self.logdir, name) oname = name i = 0 while path.exists(fullname): i += 1 name = oname + str(i) fullname = path.join(self.logdir, name) # using copyfile-unlink instead of shutil.move since we do not # want to keep a restrictive file mode set by the daemon copyfile(fpath, fullname) unlink(fpath) links.append('<a href="%s">%s</a>' % (name, escape_html(oname))) text = '<b>%s:</b> %s' % (escape_html(description) or 'Attachment', ' '.join(links)) self.out.timestamp(time) self.out.newstate('plain', '', '', '<p class="attach">%s</p>\n' % text)
def gen_funchelp(self, func): ret = [] real_func = getattr(func, 'real_func', func) if hasattr(real_func, 'help_arglist'): argspec = '(%s)' % real_func.help_arglist else: argspec = formatArgs(real_func) ret.append( self.gen_heading('Help on the %s command' % real_func.__name__)) ret.append('<p class="usage">Usage: <tt>' + escape_html(real_func.__name__ + argspec) + '</tt></p>') docstring = '\n'.join(formatDocstring(real_func.__doc__ or '')) ret.append(self.gen_markup(docstring)) return ''.join(ret)
def gen_genericdoc(self, obj): # unfortunately the Helper does not output all into its assigned output # object, so we need to redirect sys.stdout as well... with self.lock: self.strout.truncate(0) old_stdout = sys.stdout sys.stdout = self.strout try: self.helper.help(obj) finally: sys.stdout = old_stdout ret = self.strout.getvalue() return self.gen_heading('Python help on %r' % obj) + \ '<pre>' + escape_html(ret) + '</pre>'
def listsetups(group): setups = [] for setupname, info in sorted(iteritems(session.getSetupInfo())): if info is None or info['group'] != group: continue setups.append( '<tr><td><tt>%s</tt></td><td>%s</td>' '<td>%s</td><td>%s</td></tr>' % (setupname, setupname in session.loaded_setups and 'yes' or '', escape_html(info['description']), ', '.join( map(devlink, sorted(info['devices'], key=lower))))) ret.append('<table width="100%"><tr><th>Name</th><th>Loaded</th>' '<th>Description</th><th>Devices</th></tr>') ret.extend(setups) ret.append('</table>')
def _update_content(self): self.propdir = self.client.eval('session.experiment.proposalpath', '') if not self.propdir: return logfile = path.abspath( path.join(self.propdir, 'logbook', 'logbook.html')) if path.isfile(logfile): self.preview.load(QUrl('file://' + logfile)) else: self.preview.setHtml( '<style>body { font-family: sans-serif; }</style>' '<p><b>The logbook HTML file does not seem to exist.</b></p>' '<p>Please check that the file is created and accessible on ' '<b>your local computer</b> at %s. Then click ' '"refresh" above.' % escape_html(path.normpath(logfile)))
def send(self, subject, body, what=None, short=None, important=True): # pylint false positive for escape_html which is imported # from html not cgi (deprectaed) # pylint: disable=deprecated-method message = escape_html('*%s*\n\n```%s```' % (subject, body), False) for entry in self._getAllRecipients(important): self.log.debug(f'sending slack message to {entry}') try: response = self._slack.chat_postMessage(channel=entry, text=message) if response['ok']: continue except SlackApiError as e: error = e.response['error'] self.log.warning( f'Could not send slack message to {entry}: {error}')
def _labelunittext(self, text, unit, fixed): return escape_html(text) + u' <span class="unit">%s</span><span ' \ 'class="fixed">%s</span> ' % (escape_html(unit), fixed)
def wrap(text): return escape_html(text).replace('\n\n', '</p><p>'). \ replace('\n', '<br/>')
def gen_heading(self, title, id_=''): if id_: id_ = ' id="%s"' % escape_html(id_) return '<h3%s>%s</h3>' % (id_, escape_html(title))
def gen_devhelp(self, dev): ret = [] ret.append(self.gen_heading('Help on the %s device' % dev)) ret.append('<p class="devcls">%s is a device of class %s.</p>' % (dev.name, dev.__class__.__name__)) if isinstance(dev, DeviceAlias): points = dev.alias if points: ret.append('<p class="devalias">%s is a device alias, it ' 'points to <a href="dev:%s">%s</a>.' % (dev, points, points)) else: ret.append('<p class="devalias">%s is a device alias, it ' 'points to nothing at the moment.') if dev.description: ret.append('<p class="devdesc">Device description: ' + escape_html(dev.description) + '</p>') if dev.__class__.__doc__: clsdoc = '\n'.join(formatDocstring(dev.__class__.__doc__)) ret.append('<p class="clsdesc">Device class description:</p>' + '<blockquote>' + self.gen_markup(clsdoc) + '</blockquote>') ret.append('<h4>Device parameters</h4>') ret.append( '<table width="100%"><tr><th>Name</th><th>Current value</th>' '<th>Unit</th><th>Settable?</th><th>Value type</th>' '<th>Description</th></tr>') devunit = getattr(dev, 'unit', '') for name, info in sorted(iteritems(dev.parameters)): if not info.userparam: continue try: value = getattr(dev, name) except Exception: value = '<could not get value>' unit = (info.unit or '').replace('main', devunit) vstr = repr(value) if len(vstr) > 50: vstr = vstr[:47] + '...' settable = info.settable and 'yes' or 'no' name = dev.name + '.' + name if isinstance(info.type, type): ptype = info.type.__name__ else: ptype = info.type.__doc__ or '?' ret.append('<tr><td><tt>%s</tt></td><td>%s</td><td>%s</td>' '<td>%s</td><td>%s</td><td>%s</td></tr>' % (name, escape_html(vstr), escape_html(unit), settable, escape_html(ptype), escape_html(info.description))) ret.append('</table>') ret.append('<h4>Device methods</h4>') ret.append('<table width="100%"><tr><th>Method</th><th>From class</th>' '<th>Description</th></tr>') listed = set() def _list(cls): if cls in listed: return listed.add(cls) for name, (args, doc, fromtype, is_usermethod) in sorted(iteritems(cls.methods)): if is_usermethod and fromtype is cls: ret.append( '<tr><td><tt>%s</tt></td><td>%s</td><td>%s</td></tr>' % (escape_html(dev.name + '.' + name + args), cls.__name__, escape_html(doc))) for base in cls.__bases__: if issubclass(base, Device): _list(base) _list(dev.__class__) ret.append('</table>') return ''.join(ret)
def switchWarnPanel(self, on): if on: self._warnlabel.text = escape_html(self._currwarnings) else: self._warnlabel.text = ''
def initGui(self): self._content = [] self._bgcolor = 'inherit' self._black = 'black' self._yellow = 'yellow' self._green = '#00ff00' self._red = 'red' self._gray = 'gray' self._white = 'white' self._orange = '#ffa500' headprops = dict( fs=self._fontsize, fst=self._timefontsize, fsb=self._fontsizebig, ff=self.font, ffm=self.valuefont or self.font, intv=self.interval, # pylint: disable=deprecated-method title=escape_html(self.title), icon=nicos_icon, ) self += HEAD % headprops self += u'<table class="layout"><tr><td><div class="time">' self._timelabel = Label('timelabel') self += self._timelabel self += u'</div><div>' self._warnlabel = Label('warnings', back='red', text='') self += self._warnlabel self += u'</div></td></tr>\n' self._plots = {} def _create_field(blk, config): if 'widget' in config or 'gui' in config: self.log.warning('ignoring "widget" or "gui" element in HTML ' 'monitor configuration') return None field = Field(self._prefix, config) field.updateKeymap(self._keymap) if field.plot and pygr: p = self._plots.get(field.plot) if not p: p = Plot(field.plotwindow, field.width, field.height) self._plots[field.plot] = p blk += p field._plotcurve = p.addcurve(field.name) elif field.picture: # pylint: disable=deprecated-method pic = Picture(field.picture, field.width, field.height, escape_html(field.name)) blk += pic else: # deactivate plots field.plot = None # create name label # pylint: disable=deprecated-method flabel = field._namelabel = Label('name', field.width, escape_html(field.name)) blk += flabel blk += u'</td></tr><tr><td>' # create value label cls = 'value' if field.istext: cls += ' istext' vlabel = field._valuelabel = Label(cls, fore='white') blk += vlabel return field for superrow in self.layout: self += u'<tr><td class="center">\n' for column in superrow: self += u' <table class="column"><tr><td>' for block in column: block = self._resolve_block(block) blk = Block(block._options) blk += u'<div class="block">' # pylint: disable=deprecated-method blk += (u'<div class="blockhead">%s</div>' % escape_html(block._title)) blk += u'\n <table class="blocktable">' for row in block: if row is None: blk += u'<tr></tr>' else: blk += u'<tr><td class="center">' for field in row: blk += u'\n <table class="field"><tr><td>' f = _create_field(blk, field) if f and f.setups: if blk.setups: blk._onlyfields.append(f) else: self._onlyfields.append(f) blk += u'</td></tr></table> ' blk += u'\n </td></tr>' blk += u'</table>\n </div>' self += blk if blk.setups: self._onlyblocks.append(blk) self += u'</td></tr></table>\n' self += u'</td></tr>' self += u'</table>\n' self += u'</body></html>\n'
def _labelunittext(self, text, unit, fixed): # pylint: disable=deprecated-method return escape_html(text) + ' <span class="unit">%s</span><span ' \ 'class="fixed">%s</span> ' % (escape_html(unit), fixed)
def devlink(devname): if devname in session.devices: return '<a href="dev:%s">%s</a>' % (escape_html(devname), escape_html(devname)) return escape_html(devname)
def gen_helpindex(self): ret = [ '<p class="menu">' '<a href="#commands">Commands</a> | ' '<a href="#devices">Devices</a> | ' '<a href="#setups">Setups</a></p>' ] ret.append('<p>Welcome to the NICOS interactive help!</p>') cmds = [] for name, obj in session.getExportedObjects(): if not hasattr(obj, 'is_usercommand'): continue real_func = getattr(obj, 'real_func', obj) if real_func.__name__.startswith('_'): continue if getattr(real_func, 'is_hidden', False): continue if real_func.__name__ != name: # it's an alias, don't show it again continue if hasattr(real_func, 'help_arglist'): argspec = '(%s)' % real_func.help_arglist else: argspec = formatArgs(real_func) signature = '<tt><a href="cmd:%s">%s</a></tt><small>' % \ ((real_func.__name__,)*2) + escape_html(argspec) + '</small>' docstring = escape_html(real_func.__doc__ or ' ').splitlines()[0] cmds.append('<tr><td>%s</td><td>%s</td></tr>' % (signature, docstring)) cmds.sort() ret.append(self.gen_heading('NICOS commands', 'commands')) ret.append('<p>These commands are currently available.</p>') ret.append('<table width="100%">' '<tr><th>Name</th><th>Short description</th></tr>') ret.extend(cmds) ret.append('</table>') ret.append(self.gen_heading('Devices', 'devices')) ret.append( '<p>These are the currently loaded high-level devices. Use ' '<a href="cmd:AddSetup">AddSetup()</a> or the "Setup" ' 'window to add more devices.</p>') ret.append('<table width="100%"><tr><th>Name</th><th>Type</th>' '<th>From setup</th><th>Description</th></tr>') setupinfo = session.getSetupInfo() devsetups = {} for sname, info in iteritems(setupinfo): if info is None: continue for devname in info['devices']: devsetups[devname] = sname for devname in sorted(session.explicit_devices, key=lower): dev = session.devices[devname] ret.append( '<tr><td><tt><a href="dev:%s">%s</a></tt></td>' '<td>%s</td><td>%s</td><td>%s</td>' % (dev, dev, dev.__class__.__name__, devsetups.get( devname, ''), escape_html(dev.description))) ret.append('</table>') ret.append(self.gen_heading('Setups', 'setups')) ret.append('<p>These are the available setups. Use ' '<a href="cmd:AddSetup">AddSetup()</a> to load an ' 'additional setup or <a href="cmd:NewSetup">NewSetup()</a>' ' to load one or more completely new ones.</p>') def devlink(devname): if devname in session.devices: return '<a href="dev:%s">%s</a>' % (escape_html(devname), escape_html(devname)) return escape_html(devname) def listsetups(group): setups = [] for setupname, info in sorted(iteritems(session.getSetupInfo())): if info is None or info['group'] != group: continue setups.append( '<tr><td><tt>%s</tt></td><td>%s</td>' '<td>%s</td><td>%s</td></tr>' % (setupname, setupname in session.loaded_setups and 'yes' or '', escape_html(info['description']), ', '.join( map(devlink, sorted(info['devices'], key=lower))))) ret.append('<table width="100%"><tr><th>Name</th><th>Loaded</th>' '<th>Description</th><th>Devices</th></tr>') ret.extend(setups) ret.append('</table>') ret.append('<h4>Basic instrument setups</h4>') listsetups('basic') ret.append('<h4>Optional setups</h4>') listsetups('optional') ret.append('<h4>Plug-and-play setups</h4>') listsetups('plugplay') return ''.join(ret)
def switchWarnPanel(self, on): if on: # pylint: disable=deprecated-method self._warnlabel.text = escape_html(self._currwarnings) else: self._warnlabel.text = ''