Created
March 29, 2011 01:45
-
-
Save kra/891679 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
""" | |
Environment helper for cram. | |
Proof of concept, would be better implemented inside cram.py, | |
where we wouldn't have to write a tempfile; in that case, would probably want | |
to specify a prefix so we could refer to history. | |
Example usage: | |
Normal usage - the output is not regexped for clarity, but pin and txid | |
change with each POST. | |
$ $TESTDIR/client.py POST /verify/v1/call phone=5035551212 message=message | |
200 OK | |
{"stat": "OK", "response": {"pin": "7909", "txid": "0e18f346-891f-4f10-8480-828a126c846c"}} | |
We need that txid for this GET. | |
$ $TESTDIR/client.py GET /verify/v1/status txid=XXX | |
400 Bad Request | |
{"stat": "FAIL", "code": 40003, "message": "Invalid txid"} | |
Write environment to /tmp/call-env - we probably want a $SCRATCHDIR. | |
$ $TESTDIR/cram_helper.py --envout=/tmp/call_env $TESTDIR/client.py \ | |
> POST /verify/v1/call phone=5035551212 message=message | |
200 OK | |
{"stat": "OK", "response": {"pin": ".+", "txid": ".+"}} (re) | |
Now we have a very ugly env dict stored by position - we need a helper | |
for this, see comments source. Again, not regexped for clarity. | |
$ cat /tmp/call_env | |
{'cram_env_2': '{"stat":', 'cram_env_3': '"OK",', 'cram_env_0': '200', 'cram_env_1': 'OK', 'cram_env_6': '"3959",', 'cram_env_7': '"txid":', 'cram_env_4': '"response":', 'cram_env_5': '{"pin":', 'cram_env_8': '"1092e2e0-6d93-4c3f-929b-f22b3545850c"}}'} | |
Q&D clean up to make it usable - this is not happy. | |
$ $TESTDIR/env_munger.py /tmp/call_env | |
Show the cleaned up env file, not regexped for clarity. | |
$ cat /tmp/call_env | |
{'cram_env_8': 'fa28aead-583d-4040-bb71-29789532020d'} | |
Now we can test success with that env var. | |
$ $TESTDIR/cram_helper.py --envin=/tmp/call_env $TESTDIR/client.py GET /verify/v1/status txid='$cram_env_8' | |
200 OK | |
{"stat": "OK", "response": {"info": "Call request initialized", "state": "started", "event": "INITIALIZED"}} | |
""" | |
import getopt | |
import os, sys, subprocess #, shlex | |
def read_env(env_filename): | |
""" | |
Return the evaluated contetns of filename. Contents are assumed to be safe | |
to eval. | |
""" | |
env_file = open(env_filename) | |
env = eval(env_file.read()) | |
env_file.close() | |
return env | |
def write_env(env_d, env_filename): | |
""" | |
Write the repr of env_d to env_filename. | |
""" | |
env_file = open(env_filename, 'w') | |
env_file.write(repr(env_d)) | |
env_file.write('\n') | |
env_file.close() | |
def usage(): | |
sys.stderr.write( | |
'usage: %s [--json] [--xml] [--position] ' | |
'[--envin=<file>] [--envout=<file>] ' | |
'<command>...\n' | |
'only one of --json, --xml, --position can be chosen\n' % sys.argv[0]) | |
sys.exit(1) | |
def main(): | |
parse_json = False | |
parse_xml = False | |
parse_position = False | |
get_stdin = False | |
get_stderr = False | |
env_in = os.environ.copy() | |
env_out = None | |
# Since we only get args from the front, we don't need -- or similar. | |
(optlist, args) = getopt.getopt( | |
sys.argv[1:], '', | |
['json', 'xml', 'position', 'envin=', 'envout=']) | |
opt_d = dict(optlist) | |
# I want json and xml helpers, but would need a way to express how the | |
# structures should be translated into the env. Maybe it would be good | |
# enough to be able to specify that the entire parsed stream should be | |
# written to the env file, so --envin can specify the helper which should | |
# eval it. | |
if opt_d.has_key('--json'): | |
raise NotImplementedError | |
elif opt_d.has_key('--xml'): | |
raise NotImplementedError | |
elif opt_d.has_key('--position'): | |
parse_position = True | |
elif opt_d.has_key('--stdin'): | |
get_stdin = True | |
elif opt_d.has_key('--stderr'): | |
get_stderr = True | |
if opt_d.has_key('--envin'): | |
env_in.update(read_env(opt_d['--envin'])) | |
if opt_d.has_key('--envout'): | |
env_out = opt_d['--envout'] | |
# default is position | |
if not any([parse_json, parse_xml, parse_position]): | |
parse_position = True | |
# default is stdin | |
if not any([get_stdin, get_stderr]): | |
get_stdin = True | |
# choose only one | |
if len( | |
[opt for opt in [parse_json, parse_xml, parse_position] if opt]) > 1: | |
usage() | |
if len([opt for opt in [get_stdin, get_stderr] if opt]) > 1: | |
usage() | |
if len(args) < 1: | |
usage() | |
command = ' '.join(args) | |
p = subprocess.Popen(['/bin/sh', '-'], bufsize=-1, stdin=subprocess.PIPE, | |
stdout=subprocess.PIPE, stderr=subprocess.PIPE, | |
universal_newlines=True, env=env_in, | |
close_fds=os.name == 'posix') | |
p.stdin.write(' '.join(args)) | |
(stdout, stderr) = p.communicate() | |
if get_stderr: | |
stream = stderr | |
else: | |
stream = stdout | |
if env_out: | |
if parse_position: | |
# XXX should be able to specify an env var prefix | |
env_vars = dict( | |
[('cram_env_%s' % i, var) | |
for (i, var) in enumerate(stream.split())]) | |
write_env(env_vars, env_out) | |
else: | |
raise NotImplementedError # json, xml | |
sys.stdout.write(stdout) | |
sys.stderr.write(stderr) | |
sys.exit(p.returncode) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment