def xdg_data_home(request): """A fixure that creates a temporary $XDG_DATA_HOME directory.""" d = tempfile.mkdtemp() with ENV.swap(XDG_DATA_HOME=d): with environ.context(): yield d shutil.rmtree(d)
def distinct_status_dirs(d): d = expand_and_make_dir(d) t = 'FIXIE_{0}_JOBS_DIR' for x, y in itertools.combinations(QUEUE_STATUSES, 2): xd = ENV.get(t.format(x.upper()), None) yd = ENV.get(t.format(y.upper()), None) if xd is not None and yd is not None and xd == yd: msg = '${0} and ${1} must have distinct values, got {2!r}' raise ValueError(msg.format(x, y, xd)) elif xd is not None and xd == d: msg = '${0} and new value must be distinct, got {1!r}' raise ValueError(msg.format(x, d)) elif yd is not None and yd == d: msg = '${0} and new value must be distinct, got {1!r}' raise ValueError(msg.format(y, d)) return d
def verify_user(user, token, url=None): """verifies a user/token pair. This happens either locally (if creds is available) or remotely (if $FIXIE_CREDS_URL was provided). """ url = ENV.get('FIXIE_CREDS_URL', '') if url is None else url if url: return verify_user(user, token, url) else: return verify_user_local(user, token)
def test_detached_call(): with ENV.swap(FIXIE_DETACHED_CALL='test'), tempfile.NamedTemporaryFile( 'w+t') as f: child_pid = detached_call(['env'], stdout=f) status = waitpid(child_pid, timeout=10.0) f.seek(0) s = f.read() assert status assert os.getpid() != child_pid assert 'FIXIE_DETACHED_CALL=test' in s
def xdg(request): """A fixure that creates a temporary XDG base directory and sets $XDG_DATA_HOME={xdg-base}/share and $XDG_CONFIG_HOME={xdg-base}/config. """ d = tempfile.mkdtemp() data = os.path.join(d, 'share') conf = os.path.join(d, 'config') with ENV.swap(XDG_DATA_HOME=data, XDG_CONFIG_HOME=conf): with environ.context(): yield d shutil.rmtree(d)
def detached_call(args, stdout=None, stderr=None, stdin=None, env=None, **kwargs): """Runs a process and detaches it from its parent (i.e. the current process). In the parent process, this will return the PID of the child. By default, this will return redirect all streams to os.devnull. Additionally, if an environment is not provided, the current fixie environment is passed in. If close_fds is provided, it must be True. All other kwargs are passed through to Popen. Inspired by detach.call(), Copyright (c) 2014 Ryan Bourgeois. """ env = ENV.detype() if env is None else env stdin = os.open(os.devnull, os.O_RDONLY) if stdin is None else stdin stdout = os.open(os.devnull, os.O_WRONLY) if stdout is None else stdout stderr = os.open(os.devnull, os.O_WRONLY) if stderr is None else stderr if not kwargs.get('close_fds', True): raise RuntimeError('close_fds must be True.') shared_pid = multiprocessing.Value('i', 0) pid = os.fork() if pid == 0: # in child os.setsid() proc = subprocess.Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, close_fds=True, env=env) shared_pid.value = proc.pid os._exit(0) else: # in parent os.waitpid(pid, 0) child_pid = shared_pid.value del shared_pid return child_pid
def fixie_job_status_dir(status): """Ensures and returns the $FIXIE_{STATUS}_JOBS_DIR""" fsjd = os.path.join(ENV.get('FIXIE_JOBS_DIR'), status) os.makedirs(fsjd, exist_ok=True) return fsjd