def at(command, when, queue = 'a'): """ Execute command at when. command may be anything interpreble by /bin/sh. If you need features specific to another shell, create a script and then make the command <path to shell> <path to script>. when may be a datetime.timedelta, a datetime.datetime or a timespec str. If a string is provided, it is assumed that it's a valid timespec. See `timespec` doc in `at`'s documentation. """ posix_time = False if isinstance(when, datetime.datetime): timespec = convert_datetime(when) posix_time = True elif isinstance(when, datetime.timedelta): timespec = convert_timedelta(when) elif isinstance(when, basestring): timespec = when # TODO: Validate timespec? else: raise NotImplementedError('I don\'t support the class you pass'+ 'ed to schedule(). Try the builtin datetime.') # Build our `at` command line arguments... atargs = list([config.at_binary]) queue = _validate_queue(queue) if posix_time: atargs.append('-t') atargs.extend(timespec.split(" ")) if config.always_send_mail: atargs.append('-m') elif config.never_send_mail: atargs.append('-M') # Prevent creation of a needless subprocess by using a temporary file. # StringIO cannot be used due to Popen's use of fileno(). at_stdin = tempfile.TemporaryFile() at_stdin.write(command) at_stdin.seek(0) # Build our Popen keyword arguments... atkwargs = dict(stdin=at_stdin, stdout=PIPE, stderr=PIPE) if not config.inherit_env: atkwargs['env'] = config.atjob_environment sp = Popen(atargs, **atkwargs) (at_stdout, at_stderr) = sp.communicate() at_stdin.close() atjob = AtJob() atjob.from_at_stderr(at_stderr) atjob.command = command atjob.when = when atjob.who = os.getenv("LOGNAME") return atjob
def at(command, when, queue = 'a'): """ Execute command at when. command may be anything interpreble by /bin/sh. If you need features specific to another shell, create a script and then make the command <path to shell> <path to script>. when may be a datetime.timedelta, a datetime.datetime or a timespec str. If a string is provided, it is assumed that it's a valid timespec. See `timespec` doc in `at`'s documentation. python-atd also has good support for named queues. Both GNU and BSD at support the concept of named queues, which allow you to easily separate different types of jobs based on type. For example, if you owned a bank, you'd have different types of jobs. Check clearing might go in queue "c" 24 hours after request, while international wire clearing would go in queue "i" 48 hours after request. An unfortunate limitation of `at` is that all jobs can only be one letter, A-Z or a-z. This means there are only 52 available queues in both BSD at and GNU at. """ # First build our timespec for `at`... posix_time = False # Since timespecs aren't validated/parsed, we can only easily check datetime check_past = False if isinstance(when, datetime.datetime): timespec = convert_datetime(when) posix_time = True check_past = True elif isinstance(when, datetime.timedelta): timespec = convert_timedelta(when) when = datetime.datetime.now() + when check_past = True elif isinstance(when, str): timespec = when # TODO: Validate timespec? else: raise NotImplementedError('I don\'t support the class you pass'+ 'ed to schedule(). Try the builtin datetime.') if check_past: if (when < datetime.datetime.now()): raise ValueError('`when` must be at a time in the future, never in'+ ' the past') # Build our `at` command line arguments... atargs = list([config.at_binary]) queue = _validate_queue(queue) if posix_time: atargs.append('-t') atargs.extend(timespec.split(" ")) if config.always_send_mail: atargs.append('-m') elif config.never_send_mail: atargs.append('-M') atargs.append('-q') atargs.append(queue) # Prevent creation of a needless subprocess by using a temporary file. # StringIO cannot be used due to Popen's use of fileno(). at_stdin = tempfile.TemporaryFile('w') at_stdin.write(command) at_stdin.seek(0) # Build our Popen keyword arguments... atkwargs = dict(stdin=at_stdin, stdout=PIPE, stderr=PIPE) if not config.inherit_env: atkwargs['env'] = config.atjob_environment sp = Popen(atargs, **atkwargs) (at_stdout, at_stderr) = sp.communicate() at_stdin.close() # Build our AtJob object for user consumption... atjob = AtJob() atjob.from_at_stderr(at_stderr) atjob.command = command atjob.when = when atjob.queue = queue atjob.who = os.getenv("LOGNAME") return atjob
def at(command, when, queue = 'a'): """ Execute command at when. command may be anything interpreble by /bin/sh. If you need features specific to another shell, create a script and then make the command <path to shell> <path to script>. when may be a datetime.timedelta, a datetime.datetime or a timespec str. If a string is provided, it is assumed that it's a valid timespec. See `timespec` doc in `at`'s documentation. python-atd also has good support for named queues. Both GNU and BSD at support the concept of named queues, which allow you to easily separate different types of jobs based on type. For example, if you owned a bank, you'd have different types of jobs. Check clearing might go in queue "c" 24 hours after request, while international wire clearing would go in queue "i" 48 hours after request. An unfortunate limitation of `at` is that all jobs can only be one letter, A-Z or a-z. This means there are only 52 available queues in both BSD at and GNU at. """ # First build our timespec for `at`... posix_time = False # Since timespecs aren't validated/parsed, we can only easily check datetime check_past = False if isinstance(when, datetime.datetime): timespec = convert_datetime(when) posix_time = True check_past = True elif isinstance(when, datetime.timedelta): timespec = convert_timedelta(when) when = datetime.datetime.now() + when check_past = True elif isinstance(when, basestring): timespec = when # TODO: Validate timespec? else: raise NotImplementedError('I don\'t support the class you pass'+ 'ed to schedule(). Try the builtin datetime.') if check_past: if (when < datetime.datetime.now()): raise ValueError('`when` must be at a time in the future, never in'+ ' the past') # Build our `at` command line arguments... atargs = list([config.at_binary]) queue = _validate_queue(queue) if posix_time: atargs.append('-t') atargs.extend(timespec.split(" ")) if config.always_send_mail: atargs.append('-m') elif config.never_send_mail: atargs.append('-M') atargs.append('-q') atargs.append(queue) # Prevent creation of a needless subprocess by using a temporary file. # StringIO cannot be used due to Popen's use of fileno(). at_stdin = tempfile.TemporaryFile() at_stdin.write(command) at_stdin.seek(0) # Build our Popen keyword arguments... atkwargs = dict(stdin=at_stdin, stdout=PIPE, stderr=PIPE) if not config.inherit_env: atkwargs['env'] = config.atjob_environment sp = Popen(atargs, **atkwargs) (at_stdout, at_stderr) = sp.communicate() at_stdin.close() # Build our AtJob object for user consumption... atjob = AtJob() atjob.from_at_stderr(at_stderr) atjob.command = command atjob.when = when atjob.queue = queue atjob.who = os.getenv("LOGNAME") return atjob