def _clean_prior(self): """ Cleans up from a previous task that didn't exit cleanly. Returns ``True`` if previous task was cleaned. """ if self._loaded: try: pid_file = daemon.get_daemon_pidfile(self) # check if it exists so we don't raise if os.path.isfile(pid_file): # read pid from file pid = int(common.readfile(pid_file)) # check if pid file is stale if pid and not daemon.pid_exists(pid): common.safe_remove_file(pid_file) raise ValueError except (ValueError, TypeError): self._clean() return True return False
def testNotExistFile__safe_remove_file(self): """ common.safe_remove_file: doesn't raise when trying to remove a non-existent file. """ filename = self.make_file() self.clean_paths(filename) self.assertFalse(common.safe_remove_file(filename))
def _clean(self): """ Cleans up an active task and resets its data. """ common.safe_remove_file(self._paths['active_file']) self._reset()
def testExistFile__safe_remove_file(self): """ common.safe_remove_file: removes existing file. """ filename = self.make_file() self.assertTrue(common.safe_remove_file(filename))
def _edit_task_config(env, task_config, confirm): """ Launches text editor to edit provided task configuration file. `env` Runtime ``Environment`` instance. `task_config` Path to task configuration file. `confirm` If task config is invalid after edit, prompt to re-edit. Return boolean. * Raises ``InvalidTaskConfig`` if edited task config fails to parse and `confirm` is ``False``. """ # get editor program if common.IS_MACOSX: def_editor = "open" else: def_editor = "vi" editor = os.environ.get("EDITOR", def_editor) def _edit_file(filename): """ Launches editor for given filename. """ proc = subprocess.Popen("{0} {1}".format(editor, filename), shell=True) proc.communicate() if proc.returncode == 0: try: # parse temp configuration file parser_ = parser.parse_config(filename, "task") registration.run_option_hooks(parser_, disable_missing=False) except (parser.ParseError, errors.InvalidTaskConfig) as exc: reason = unicode(getattr(exc, "reason", exc)) raise errors.InvalidTaskConfig(task_config, reason=reason) return True else: return False try: # create temp copy of task config fd, tmpname = tempfile.mkstemp(suffix=".cfg", prefix="focus_") with open(task_config, "r") as file_: os.write(fd, file_.read()) os.close(fd) while True: try: # launch editor if not _edit_file(tmpname): return False # overwrite original with temp with open(tmpname, "r") as temp: with open(task_config, "w", 0) as config: config.write(temp.read()) return True except errors.InvalidTaskConfig as exc: if not confirm: raise # reraise # prompt to re-edit env.io.error(unicode(exc)) while True: try: resp = env.io.prompt("Would you like to retry? (y/n) ") resp = resp.strip().lower() except KeyboardInterrupt: return True if resp == "y": break elif resp == "n": return True except OSError: return False finally: common.safe_remove_file(tmpname) # cleanup temp
def _cleanup_pid(): """ Removes pidfile. """ common.safe_remove_file(filename)
def _handle_block(self, task, disable=False): """ Handles blocking domains using hosts file. `task` ``Task`` instance. `disable` Set to ``True``, to turn off blocking and restore hosts file; otherwise, ``False`` will enable blocking by updating hosts file. Returns boolean. """ backup_file = os.path.join(task.task_dir, '.hosts.bak') self.orig_data = self.orig_data or common.readfile(backup_file) self.last_updated = self.last_updated or -1 if not self.orig_data: # should't attempt restore without good original data, bail if disable: return False # attempt to fetch data from the source self.orig_data = common.readfile(self.hosts_file) if not self.orig_data: return False # restore backup if not os.path.exists(backup_file): common.writefile(backup_file, self.orig_data) # bail early if hosts file modification time hasn't changed try: should_write = (disable or self.last_updated != os.path.getmtime(self.hosts_file)) except OSError: should_write = True # file was removed, let's write! if not should_write: return True # make copy of original data, in case we need to modify data = self.orig_data # if not restoring, tack on domains mapped # to localhost to end of file data if not disable: # convert the set to a list and sort domains = list(self.domains) domains.sort() data += ('\n'.join('127.0.0.1\t{0}\t# FOCUS' .format(d) for d in domains) + '\n') # make temp file with new host file data with tempfile.NamedTemporaryFile(prefix='focus_') as tempf: tempf.write(data) tempf.flush() # overwrite hosts file with our modified copy. if not self.run_root('cp "{0}" "{1}"'.format(tempf.name, self.hosts_file)): return False # MacOS X generally requires flushing the system dns cache to pick # up changes to the hosts file: # dscacheutil -flushcache or lookupd -flushcache if common.IS_MACOSX: dscacheutil, lookupd = [common.which(x) for x in ('dscacheutil', 'lookupd')] self.run_root(' '.join([dscacheutil or lookupd, '-flushcache'])) if disable: common.safe_remove_file(backup_file) # cleanup the backup # store last modification time try: self.last_updated = os.path.getmtime(self.hosts_file) except OSError: # file was removed, let's update next time around self.last_updated = -1 return True
def _edit_task_config(env, task_config, confirm): """ Launches text editor to edit provided task configuration file. `env` Runtime ``Environment`` instance. `task_config` Path to task configuration file. `confirm` If task config is invalid after edit, prompt to re-edit. Return boolean. * Raises ``InvalidTaskConfig`` if edited task config fails to parse and `confirm` is ``False``. """ # get editor program if common.IS_MACOSX: def_editor = 'open' else: def_editor = 'vi' editor = os.environ.get('EDITOR', def_editor) def _edit_file(filename): """ Launches editor for given filename. """ proc = subprocess.Popen('{0} {1}'.format(editor, filename), shell=True) proc.communicate() if proc.returncode == 0: try: # parse temp configuration file parser_ = parser.parse_config(filename, 'task') registration.run_option_hooks(parser_, disable_missing=False) except (parser.ParseError, errors.InvalidTaskConfig) as exc: reason = unicode(getattr(exc, 'reason', exc)) raise errors.InvalidTaskConfig(task_config, reason=reason) return True else: return False try: # create temp copy of task config fd, tmpname = tempfile.mkstemp(suffix='.cfg', prefix='focus_') with open(task_config, 'r') as file_: os.write(fd, file_.read()) os.close(fd) while True: try: # launch editor if not _edit_file(tmpname): return False # overwrite original with temp with open(tmpname, 'r') as temp: with open(task_config, 'w', 0) as config: config.write(temp.read()) return True except errors.InvalidTaskConfig as exc: if not confirm: raise # reraise # prompt to re-edit env.io.error(unicode(exc)) while True: try: resp = env.io.prompt('Would you like to retry? (y/n) ') resp = resp.strip().lower() except KeyboardInterrupt: return True if resp == 'y': break elif resp == 'n': return True except OSError: return False finally: common.safe_remove_file(tmpname) # cleanup temp
def _handle_block(self, task, disable=False): """ Handles blocking domains using hosts file. `task` ``Task`` instance. `disable` Set to ``True``, to turn off blocking and restore hosts file; otherwise, ``False`` will enable blocking by updating hosts file. Returns boolean. """ backup_file = os.path.join(task.task_dir, '.hosts.bak') self.orig_data = self.orig_data or common.readfile(backup_file) self.last_updated = self.last_updated or -1 if not self.orig_data: # should't attempt restore without good original data, bail if disable: return False # attempt to fetch data from the source self.orig_data = common.readfile(self.hosts_file) if not self.orig_data: return False # restore backup if not os.path.exists(backup_file): common.writefile(backup_file, self.orig_data) # bail early if hosts file modification time hasn't changed try: should_write = ( disable or self.last_updated != os.path.getmtime(self.hosts_file)) except OSError: should_write = True # file was removed, let's write! if not should_write: return True # make copy of original data, in case we need to modify data = self.orig_data # if not restoring, tack on domains mapped # to localhost to end of file data if not disable: # convert the set to a list and sort domains = list(self.domains) domains.sort() data += ('\n'.join('127.0.0.1\t{0}\t# FOCUS'.format(d) for d in domains) + '\n') # make temp file with new host file data with tempfile.NamedTemporaryFile(prefix='focus_') as tempf: tempf.write(data) tempf.flush() # overwrite hosts file with our modified copy. if not self.run_root('cp "{0}" "{1}"'.format( tempf.name, self.hosts_file)): return False # MacOS X generally requires flushing the system dns cache to pick # up changes to the hosts file: # dscacheutil -flushcache or lookupd -flushcache if common.IS_MACOSX: dscacheutil, lookupd = [ common.which(x) for x in ('dscacheutil', 'lookupd') ] self.run_root(' '.join([dscacheutil or lookupd, '-flushcache'])) if disable: common.safe_remove_file(backup_file) # cleanup the backup # store last modification time try: self.last_updated = os.path.getmtime(self.hosts_file) except OSError: # file was removed, let's update next time around self.last_updated = -1 return True