Add "py", a CLI for python one-liners

This commit is contained in:
2022-10-17 13:54:32 +00:00
parent d81993b78c
commit 821face234
2 changed files with 130 additions and 0 deletions

54
.mgr_config/bin/py Normal file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import argparse
import sys
from pathlib import Path
source = " ".join(sys.argv[1:])
INPUT_SRC_NAME = "<py-input>"
global_vars = {}
local_vars = {}
py_env_conf = Path.home() / ".py-env.py"
if py_env_conf.exists():
with open(Path.home() / ".py-env.py") as f:
code = compile(f.read(), "py-env.py", "exec")
exec(code)
try:
code = compile(source, INPUT_SRC_NAME, "eval")
val = eval(code)
# If it's a string, just print it
if type(val) == str:
print(val)
exit(0)
# If it's not iterable, just print it
try:
it = iter(val)
except TypeError as e:
if val is not None:
print(val)
exit(0)
# It's iterable, print each element as a line
try:
for item in val:
print(item)
exit(0)
except Exception as e:
e.args = ("Failed to print all elements",) + e.args
raise
except (SyntaxError, NameError) as e:
pass
try:
code = compile(source, INPUT_SRC_NAME, "exec")
exec(code)
except (SyntaxError, NameError) as e:
e.args = ("Invalid Python code",) + e.args
raise e

76
.py-env.py Normal file
View File

@@ -0,0 +1,76 @@
import itertools
import json
import operator
import os
import sys
import yaml
from functools import partial, reduce
from math import *
from pathlib import Path
from itertools import chain
try:
from tabulate import tabulate
except ImportError:
pass
try:
import rich
from rich import inspect, print as pp
except ImportError:
pass
# Always write heavyweight/blocking code in this file lazily to keep startup
# time short. In the same vein, be careful not to consume stdin unless an object
# in this file is called or iterated upon, e.g. stdin_str()
# Returns a lazily-evaluable map which executes multiple map functions
def maps(items, *map_funs):
it = items
for func in map_funs:
it = map(func, it)
return it
# Returns a lazily-evaluable filter which executes multiple predicate functions
def filters(items, *pred_funs):
it = items
for pred in pred_funs:
it = filter(pred, it)
return it
# Concatenate two items, there's likely a safer way to do this to avoid summing ints
concat = lambda a, b: "".join([a, b])
# Joins an interable of strings
join = "".join
# Return an iterable for file. This doesn't close the handle, but for this
# little scripting interface this is fine.
def read(filename):
return open(filename, "r")
def read_str(filename):
return concats(read(filename))
stdin_str = sys.stdin.read
# An iterable which yields the characters of stdin
stdin = (c for l in sys.stdin for c in l)
# An iterable which yields the lines of stdin
lines = map(str.strip, sys.stdin)
# An iterable which yields integers supplied via stdin lines
ints = map(int, lines)
# An iterable which yields the bytes of stdin
byts = map(lambda x: bytes(x, "utf-8"), stdin) # better name? 'bytes' is taken
jr = json.loads
jw = json.dumps
yr = lambda x: yaml.load(x, Loader=yaml.SafeLoader)
yw = yaml.dump
pwd = Path.cwd()