def test_os_errors_from_popen_are_caught(self): with mock.patch('subprocess.Popen', mock.Mock(side_effect=OSError(42, u'foobar'))): out, err, code = helper.call_cmd( ['does_not_matter_as_subprocess_popen_is_mocked']) self.assertEqual(out, u'') self.assertEqual(err, u'foobar') self.assertEqual(code, 42)
def test_no_such_command(self): out, err, code = helper.call_cmd(['thiscommandabsolutelydoesntexist']) self.assertEqual(out, u'') # We don't control the output of err, the shell does. Therefore simply # assert that the shell said *something* self.assertNotEqual(err, u'') self.assertEqual(code, errno.ENOENT)
def test_bad_argument(self): out, err, code = helper.call_cmd(['cat', '-Y']) self.assertEqual(out, u'') self.assertNotEqual(err, u'') # We don't control this, although 1 might be a fairly safe guess, we # know for certain it should *not* return 0 self.assertNotEqual(code, 0)
def apply(self, ui): # abort if command unset if not self.cmdlist: ui.notify(self.noop_msg, priority="error") return # get messages to pipe if self.whole_thread: thread = ui.current_buffer.get_selected_thread() if not thread: return to_print = thread.get_messages().keys() else: to_print = [ui.current_buffer.get_selected_message()] # ask for confirmation if needed if self.confirm_msg: if (yield ui.choice(self.confirm_msg, select="yes", cancel="no")) == "no": return # prepare message sources mailstrings = [] if self.ids: mailstrings = [e.get_message_id() for e in to_print] else: mails = [m.get_email() for m in to_print] if self.decode: for mail in mails: headertext = extract_headers(mail) bodytext = extract_body(mail) msg = "%s\n\n%s" % (headertext, bodytext) mailstrings.append(msg.encode("utf-8")) else: mailstrings = [e.as_string() for e in mails] if not self.separately: mailstrings = ["\n\n".join(mailstrings)] # do teh monkey for mail in mailstrings: ui.logger.debug("%s" % mail) out, err, retval = helper.call_cmd(self.cmdlist, stdin=mail) if err: ui.notify(err, priority="error") return # display 'done' message if self.done_msg: ui.notify(self.done_msg)
def dimapseminar(ui): """interprets DIMAP seminar mails""" msg = ui.current_buffer.get_selected_message() msgtext = msg.accumulate_body() r = r"Title:\s*(?P<title>((.*)(\n\s*.*)*))\n\nSpeaker:\s*(?P<speaker>.*)\nTime:\s*(?P<time>.*)\nLocation:\s*(?P<location>.*)\n\s*Abstract:\s*(?P<abstract>((.*)\n)*)" info = re.search(r, msgtext).groupdict() info['title'] = ' '.join(info['title'].split()) #ui.notify('info: %s' % str(info.items())) cmd = "gcalcli add " \ "--calendar uni " \ "--title \"DIMAP: {speaker}:{title}\" " \ "--where \"{location}\" " \ "--when \"{time}\" "\ "--description \"{abstract}\" "\ "--duration 60 "\ "--reminder 30" cmdlist = split_commandstring(cmd.format(**info)) msg = ui.notify('info: %s' % cmdlist) if (yield ui.choice("commit?", select='yes', cancel='no')) == 'no': return ui.clear_notify([msg]) ui.notify('info: %s' % str(call_cmd(cmdlist)))
def dimapseminar(ui): """interprets DIMAP seminar mails""" msg = ui.current_buffer.get_selected_message() msgtext = msg.accumulate_body() r = r"Title:\s*(?P<title>((.*)(\n\s*.*)*))\n\nSpeaker:\s*(?P<speaker>.*)\nTime:\s*(?P<time>.*)\nLocation:\s*(?P<location>.*)\n\s*Abstract:\s*(?P<abstract>((.*)\n)*)" info = re.search(r, msgtext).groupdict() info["title"] = " ".join(info["title"].split()) # ui.notify('info: %s' % str(info.items())) cmd = ( "gcalcli add " "--calendar uni " '--title "DIMAP: {speaker}:{title}" ' '--where "{location}" ' '--when "{time}" ' '--description "{abstract}" ' "--duration 60 " "--reminder 30" ) cmdlist = split_commandstring(cmd.format(**info)) msg = ui.notify("info: %s" % cmdlist) if (yield ui.choice("commit?", select="yes", cancel="no")) == "no": return ui.clear_notify([msg]) ui.notify("info: %s" % str(call_cmd(cmdlist)))
def extract_body(mail, types=None): """ returns a body text string for given mail. If types is `None`, `text/*` is used: In case mail has a `text/html` part, it is prefered over `text/plain` parts. :param mail: the mail to use :type mail: :class:`email.Message` :param types: mime content types to use for body string :type types: list of str """ html = list(typed_subpart_iterator(mail, 'text', 'html')) # if no specific types are given, we favor text/html over text/plain drop_plaintext = False if html and not types: drop_plaintext = True body_parts = [] for part in mail.walk(): ctype = part.get_content_type() logging.debug(ctype) if types is not None: if ctype not in types: continue cd = part.get('Content-Disposition', '') if cd.startswith('attachment'): continue enc = part.get_content_charset() or 'ascii' raw_payload = part.get_payload(decode=True) if ctype == 'text/plain' and not drop_plaintext: raw_payload = string_decode(raw_payload, enc) body_parts.append(string_sanitize(raw_payload)) else: #get mime handler key = 'copiousoutput' handler, entry = settings.mailcap_find_match(ctype, key=key) if entry: # open tempfile, respect mailcaps nametemplate nametemplate = entry.get('nametemplate', '%s') prefix, suffix = parse_mailcap_nametemplate(nametemplate) tmpfile = tempfile.NamedTemporaryFile(delete=False, prefix=prefix, suffix=suffix) # write payload to tmpfile tmpfile.write(raw_payload) tmpfile.close() # read parameter, create handler command parms = tuple(map('='.join, part.get_params())) # create and call external command cmd = mailcap.subst(entry['view'], ctype, filename=tmpfile.name, plist=parms) logging.debug('command: %s' % cmd) logging.debug('parms: %s' % str(parms)) cmdlist = split_commandstring(cmd) # call handler rendered_payload, errmsg, retval = helper.call_cmd(cmdlist) # remove tempfile os.unlink(tmpfile.name) if rendered_payload: # handler had output body_parts.append(string_sanitize(rendered_payload)) return u'\n\n'.join(body_parts)
def extract_body(mail, types=None): """ returns a body text string for given mail. If types is `None`, `text/*` is used: The exact preferred type is specified by the prefer_plaintext config option which defaults to text/html. :param mail: the mail to use :type mail: :class:`email.Message` :param types: mime content types to use for body string :type types: list of str """ preferred = 'text/plain' if settings.get( 'prefer_plaintext') else 'text/html' has_preferred = False # see if the mail has our preferred type if types is None: has_preferred = list( typed_subpart_iterator(mail, *preferred.split('/'))) body_parts = [] for part in mail.walk(): ctype = part.get_content_type() if types is not None: if ctype not in types: continue cd = part.get('Content-Disposition', '') if cd.startswith('attachment'): continue # if the mail has our preferred type, we only keep this type # note that if types != None, has_preferred always stays False if has_preferred and ctype != preferred: continue enc = part.get_content_charset() or 'ascii' raw_payload = part.get_payload(decode=True) if ctype == 'text/plain': raw_payload = string_decode(raw_payload, enc) body_parts.append(string_sanitize(raw_payload)) else: # get mime handler key = 'copiousoutput' handler, entry = settings.mailcap_find_match(ctype, key=key) tempfile_name = None stdin = None if entry: handler_raw_commandstring = entry['view'] # in case the mailcap defined command contains no '%s', # we pipe the files content to the handling command via stdin if '%s' in handler_raw_commandstring: # open tempfile, respect mailcaps nametemplate nametemplate = entry.get('nametemplate', '%s') prefix, suffix = parse_mailcap_nametemplate(nametemplate) tmpfile = tempfile.NamedTemporaryFile(delete=False, prefix=prefix, suffix=suffix) # write payload to tmpfile tmpfile.write(raw_payload) tmpfile.close() tempfile_name = tmpfile.name else: stdin = raw_payload # read parameter, create handler command parms = tuple(map('='.join, part.get_params())) # create and call external command cmd = mailcap.subst(entry['view'], ctype, filename=tempfile_name, plist=parms) logging.debug('command: %s' % cmd) logging.debug('parms: %s' % str(parms)) cmdlist = split_commandstring(cmd) # call handler rendered_payload, errmsg, retval = helper.call_cmd(cmdlist, stdin=stdin) # remove tempfile if tempfile_name: os.unlink(tempfile_name) if rendered_payload: # handler had output body_parts.append(string_sanitize(rendered_payload)) return u'\n\n'.join(body_parts)
def test_stdin(self): out, err, code = helper.call_cmd(['cat'], stdin='�') self.assertEqual(out, u'�') self.assertEqual(err, u'') self.assertEqual(code, 0)
def test_no_stdin_unicode(self): out, err, code = helper.call_cmd(['echo', '-n', '�']) self.assertEqual(out, u'�') self.assertEqual(err, u'') self.assertEqual(code, 0)
def extract_body(mail, types=None): """ returns a body text string for given mail. If types is `None`, `text/*` is used: In case mail has a `text/html` part, it is prefered over `text/plain` parts. :param mail: the mail to use :type mail: :class:`email.Message` :param types: mime content types to use for body string :type types: list of str """ html = list(typed_subpart_iterator(mail, 'text', 'html')) # if no specific types are given, we favor text/html over text/plain drop_plaintext = False if html and not types: drop_plaintext = True body_parts = [] for part in mail.walk(): ctype = part.get_content_type() if types is not None: if ctype not in types: continue cd = part.get('Content-Disposition', '') if cd.startswith('attachment'): continue enc = part.get_content_charset() or 'ascii' raw_payload = part.get_payload(decode=True) if ctype == 'text/plain' and not drop_plaintext: raw_payload = string_decode(raw_payload, enc) body_parts.append(string_sanitize(raw_payload)) else: #get mime handler key = 'copiousoutput' handler, entry = settings.mailcap_find_match(ctype, key=key) if entry: # open tempfile, respect mailcaps nametemplate nametemplate = entry.get('nametemplate', '%s') prefix, suffix = parse_mailcap_nametemplate(nametemplate) tmpfile = tempfile.NamedTemporaryFile(delete=False, prefix=prefix, suffix=suffix) # write payload to tmpfile tmpfile.write(raw_payload) tmpfile.close() # read parameter, create handler command parms = tuple(map('='.join, part.get_params())) # create and call external command cmd = mailcap.subst(entry['view'], ctype, filename=tmpfile.name, plist=parms) logging.debug('command: %s' % cmd) logging.debug('parms: %s' % str(parms)) cmdlist = split_commandstring(cmd) # call handler rendered_payload, errmsg, retval = helper.call_cmd(cmdlist) # remove tempfile os.unlink(tmpfile.name) if rendered_payload: # handler had output body_parts.append(string_sanitize(rendered_payload)) return u'\n\n'.join(body_parts)
def extract_body(mail, types=None): """ returns a body text string for given mail. If types is `None`, `text/*` is used: The exact preferred type is specified by the prefer_plaintext config option which defaults to text/html. :param mail: the mail to use :type mail: :class:`email.Message` :param types: mime content types to use for body string :type types: list of str """ preferred = 'text/plain' if settings.get('prefer_plaintext') else 'text/html' has_preferred = False # see if the mail has our preferred type if types == None: has_preferred = list(typed_subpart_iterator(mail, *preferred.split('/'))) body_parts = [] for part in mail.walk(): ctype = part.get_content_type() if types is not None: if ctype not in types: continue cd = part.get('Content-Disposition', '') if cd.startswith('attachment'): continue # if the mail has our preferred type, we only keep this type # note that if types != None, has_preferred always stays False if has_preferred and ctype != preferred: continue enc = part.get_content_charset() or 'ascii' raw_payload = part.get_payload(decode=True) if ctype == 'text/plain': raw_payload = string_decode(raw_payload, enc) body_parts.append(string_sanitize(raw_payload)) else: #get mime handler key = 'copiousoutput' handler, entry = settings.mailcap_find_match(ctype, key=key) tempfile_name = None stdin = None if entry: handler_raw_commandstring = entry['view'] # in case the mailcap defined command contains no '%s', # we pipe the files content to the handling command via stdin if '%s' in handler_raw_commandstring: # open tempfile, respect mailcaps nametemplate nametemplate = entry.get('nametemplate', '%s') prefix, suffix = parse_mailcap_nametemplate(nametemplate) tmpfile = tempfile.NamedTemporaryFile(delete=False, prefix=prefix, suffix=suffix) # write payload to tmpfile tmpfile.write(raw_payload) tmpfile.close() tempfile_name = tmpfile.name else: stdin = raw_payload # read parameter, create handler command parms = tuple(map('='.join, part.get_params())) # create and call external command cmd = mailcap.subst(entry['view'], ctype, filename=tempfile_name, plist=parms) logging.debug('command: %s' % cmd) logging.debug('parms: %s' % str(parms)) cmdlist = split_commandstring(cmd) # call handler rendered_payload, errmsg, retval = helper.call_cmd(cmdlist, stdin=stdin) # remove tempfile if tempfile_name: os.unlink(tempfile_name) if rendered_payload: # handler had output body_parts.append(string_sanitize(rendered_payload)) return u'\n\n'.join(body_parts)
def test_no_stdin(self): out, err, code = helper.call_cmd(['echo', '-n', 'foo']) self.assertEqual(out, 'foo') self.assertEqual(err, '') self.assertEqual(code, 0)