<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Cron wrapper for python 2.7 and unix. Wrap your cron job to improve monitoring flexibility.

examples:

    ./superwrap.py --name foo --mail-to <EMAIL> --mail-from <EMAIL> --email-on-success --include-stdout-in-email --testing-email-mode --cmd="ls -l"
    ./superwrap.py --name foo --mail-to <EMAIL> --mail-from <EMAIL> --email-on-success --include-stdout-in-email --testing-email-mode --cmd="ls -l asdf"

responds to environment variables (these are overridden by command-line params with the same names):

* SUPERWRAP_SMTP_HOST
* SUPERWRAP_MAIL_TO or MAILTO
* SUPERWRAP_MAIL_FROM

also see:

* https://github.com/Doist/cronwrap

"""

import argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import getpass
import os
import smtplib
import socket
import tempfile
import time


# mimic gmail's monospace formatting
HTML_TMPL = """<div style="font-family:monospace; font-size:13px;">%s</div>"""

SUBJECT_LINE_TMPL = "%(result)s: %(username)s@%(hostname)s %(name)s"

STANDARD_MSG_TMPL = """%(desc)scommand:

    %(cmd)s

completed in: %(run_time).2f seconds
return code: %(return_code)s
host: %(hostname)s
user: %(username)s
output written to: %(outfile)s (%(outfile_size)d bytes)
stderr written to: %(errfile)s (%(errfile_size)d bytes)
"""

STDOUT_MSG_TMPL = """
standard out:

%s
"""

ERROR_MSG_TMPL = """
standard error:

%s
"""


# adapted from https://github.com/Doist/cronwrap
class Command:
    """Runs a command, only works on Unix.

       Example of usage::

           cmd = Command('ls')
           print cmd.stdout
           print cmd.stderr
           print cmd.return_code
           print cmd.run_time
    """
    def __init__(self, command, args_outfile=None, args_errfile=None):
        outfile = args_outfile if args_outfile else tempfile.mkstemp()[1]
        errfile = args_errfile if args_errfile else tempfile.mkstemp()[1]

        # TODO: this is bash specific - use python subprocess instead
        t_start = time.time()
        self.return_code = os.system("( %s ) > %s 2> %s" % (command, outfile, errfile))
        self.run_time = time.time() - t_start
        self.stdout = open(outfile, "r").read().strip()
        self.stderr = open(errfile, "r").read().strip()

        if not args_outfile:
            os.remove(outfile)
        if not args_errfile:
            os.remove(errfile)


class Mailer:
    """Send a fancy email message, formatted in html to give us a monospace font"""
    def __init__(self, smtp_host, from_addr, to_addrs, subject_prefix, testing_mode):
        self.smtp_args = {}
        if smtp_host:
            self.smtp_args['host'] = smtp_host
        self.from_addr = from_addr
        self.to_addrs = ",".join(to_addrs)
        self.subject_prefix = subject_prefix
        self.testing_mode = True if testing_mode is True else False

    @staticmethod
    def format_message_as_html(message):
        """Take a message and format it in a nice monospace font."""
        html = message.replace(r'  ', ' &nbsp;').replace('\n', '\n<br>').replace('\r', '')
        return HTML_TMPL % html

    def send_email(self, subject, body):
        # see http://docs.python.org/2/library/email-examples.html#id5
        msg = MIMEMultipart('alternative')
        msg['Subject'] = "%s %s" % (self.subject_prefix, subject) if self.subject_prefix else subject
        msg['From'] = self.from_addr
        msg['To'] = self.to_addrs
        msg.attach(MIMEText(body, 'plain'))
        msg.attach(MIMEText(Mailer.format_message_as_html(body), 'html'))  # html content should be last
        if self.testing_mode:
            print msg
        else:
            try:
                s = smtplib.SMTP(**self.smtp_args)
                #s.set_debuglevel(True)
                s.sendmail(self.from_addr, self.to_addrs, msg.as_string())
            finally:
                s.quit()


def _truncate(str, maxlen=10000):
    """truncate a string to at most maxlen bytes"""
    return str \
        if len(str) <= maxlen \
        else str[:maxlen] + "...\n(truncated, showing %d of %d characters)" % (maxlen, len(str))
<commit_msg>fix unknown variable s in smtp error handling<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Cron wrapper for python 2.7 and unix. Wrap your cron job to improve monitoring flexibility.

examples:

    ./superwrap.py --name foo --mail-to <EMAIL> --mail-from <EMAIL> --email-on-success --include-stdout-in-email --testing-email-mode --cmd="ls -l"
    ./superwrap.py --name foo --mail-to <EMAIL> --mail-from <EMAIL> --email-on-success --include-stdout-in-email --testing-email-mode --cmd="ls -l asdf"

responds to environment variables (these are overridden by command-line params with the same names):

* SUPERWRAP_SMTP_HOST
* SUPERWRAP_MAIL_TO or MAILTO
* SUPERWRAP_MAIL_FROM

also see:

* https://github.com/Doist/cronwrap

"""

import argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import getpass
import os
import smtplib
import socket
import tempfile
import time


# mimic gmail's monospace formatting
HTML_TMPL = """<div style="font-family:monospace; font-size:13px;">%s</div>"""

SUBJECT_LINE_TMPL = "%(result)s: %(username)s@%(hostname)s %(name)s"

STANDARD_MSG_TMPL = """%(desc)scommand:

    %(cmd)s

completed in: %(run_time).2f seconds
return code: %(return_code)s
host: %(hostname)s
user: %(username)s
output written to: %(outfile)s (%(outfile_size)d bytes)
stderr written to: %(errfile)s (%(errfile_size)d bytes)
"""

STDOUT_MSG_TMPL = """
standard out:

%s
"""

ERROR_MSG_TMPL = """
standard error:

%s
"""


# adapted from https://github.com/Doist/cronwrap
class Command:
    """Runs a command, only works on Unix.

       Example of usage::

           cmd = Command('ls')
           print cmd.stdout
           print cmd.stderr
           print cmd.return_code
           print cmd.run_time
    """
    def __init__(self, command, args_outfile=None, args_errfile=None):
        outfile = args_outfile if args_outfile else tempfile.mkstemp()[1]
        errfile = args_errfile if args_errfile else tempfile.mkstemp()[1]

        # TODO: this is bash specific - use python subprocess instead
        t_start = time.time()
        self.return_code = os.system("( %s ) > %s 2> %s" % (command, outfile, errfile))
        self.run_time = time.time() - t_start
        self.stdout = open(outfile, "r").read().strip()
        self.stderr = open(errfile, "r").read().strip()

        if not args_outfile:
            os.remove(outfile)
        if not args_errfile:
            os.remove(errfile)


class Mailer:
    """Send a fancy email message, formatted in html to give us a monospace font"""
    def __init__(self, smtp_host, from_addr, to_addrs, subject_prefix, testing_mode):
        self.smtp_args = {}
        if smtp_host:
            self.smtp_args['host'] = smtp_host
        self.from_addr = from_addr
        self.to_addrs = ",".join(to_addrs)
        self.subject_prefix = subject_prefix
        self.testing_mode = True if testing_mode is True else False

    @staticmethod
    def format_message_as_html(message):
        """Take a message and format it in a nice monospace font."""
        html = message.replace(r'  ', ' &nbsp;').replace('\n', '\n<br>').replace('\r', '')
        return HTML_TMPL % html

    def send_email(self, subject, body):
        # see http://docs.python.org/2/library/email-examples.html#id5
        msg = MIMEMultipart('alternative')
        msg['Subject'] = "%s %s" % (self.subject_prefix, subject) if self.subject_prefix else subject
        msg['From'] = self.from_addr
        msg['To'] = self.to_addrs
        msg.attach(MIMEText(body, 'plain'))
        msg.attach(MIMEText(Mailer.format_message_as_html(body), 'html'))  # html content should be last
        if self.testing_mode:
            print msg
        else:
            s = smtplib.SMTP(**self.smtp_args)
            try:
                #s.set_debuglevel(True)
                s.sendmail(self.from_addr, self.to_addrs, msg.as_string())
            finally:
                s.quit()


def _truncate(str, maxlen=10000):
    """truncate a string to at most maxlen bytes"""
    return str \
        if len(str) <= maxlen \
        else str[:maxlen] + "...\n(truncated, showing %d of %d characters)" % (maxlen, len(str))

{'fraction_non_alphanumeric': 0.1330780277644806, 'fraction_numerical': 0.003829583532790809, 'mean_word_length': 2.858264081255771, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 21, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '597870', 'n_tokens_mistral': 2834, 'n_tokens_neox': 2742, 'n_words': 701}