File: pycalc.pyw 1 #!/usr/bin/python3 2 3 # The MIT License (MIT) 4 # 5 # Copyright © 2024 pacman64 6 # 7 # Permission is hereby granted, free of charge, to any person obtaining a copy 8 # of this software and associated documentation files (the “Software”), to deal 9 # in the Software without restriction, including without limitation the rights 10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 # copies of the Software, and to permit persons to whom the Software is 12 # furnished to do so, subject to the following conditions: 13 # 14 # The above copyright notice and this permission notice shall be included in 15 # all copies or substantial portions of the Software. 16 # 17 # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 # SOFTWARE. 24 25 26 # pycalc.pyw 27 # 28 # PYthon CALCulator is a GUI app which live-evaluates the python expression 29 # currently in its single-line input, re-running it as it changes. 30 31 32 from json import dumps 33 34 import math 35 from math import \ 36 acos, acosh, asin, asinh, atan, atan2, atanh, ceil, comb, \ 37 copysign, cos, cosh, degrees, dist, e, erf, erfc, exp, expm1, \ 38 fabs, factorial, floor, fmod, frexp, fsum, gamma, gcd, hypot, inf, \ 39 isclose, isfinite, isinf, isnan, isqrt, lcm, ldexp, lgamma, log, \ 40 log10, log1p, log2, modf, nan, nextafter, perm, pi, pow, prod, \ 41 radians, remainder, sin, sinh, sqrt, tan, tanh, tau, trunc, ulp 42 try: 43 from math import cbrt, exp2 44 except Exception: 45 pass 46 47 from random import \ 48 betavariate, choice, choices, expovariate, gammavariate, gauss, \ 49 getrandbits, getstate, lognormvariate, normalvariate, paretovariate, \ 50 randbytes, randint, random, randrange, sample, seed, setstate, \ 51 shuffle, triangular, uniform, vonmisesvariate, weibullvariate 52 53 from statistics import \ 54 bisect_left, bisect_right, fmean, \ 55 geometric_mean, harmonic_mean, mean, median, \ 56 median_grouped, median_high, median_low, mode, multimode, pstdev, \ 57 pvariance, quantiles, stdev, variance 58 try: 59 from statistics import \ 60 correlation, covariance, linear_regression, mul, reduce 61 except Exception: 62 pass 63 64 from tkinter import Tk, Entry, Label, RIGHT, LEFT, EventType 65 from typing import Callable, Iterable, Any 66 67 68 # some convenience aliases to various funcs from the python stdlib 69 geomean = geometric_mean 70 harmean = harmonic_mean 71 sd = stdev 72 popsd = pstdev 73 var = variance 74 popvar = pvariance 75 randbeta = betavariate 76 randexp = expovariate 77 randgamma = gammavariate 78 randlognorm = lognormvariate 79 randnorm = normalvariate 80 randweibull = weibullvariate 81 82 # some occasionally-useful values 83 kb = 1024 84 mb = 1024 * kb 85 gb = 1024 * mb 86 tb = 1024 * gb 87 pb = 1024 * tb 88 mole = 602214076000000000000000 89 mol = mole 90 91 92 def check_shortcuts(event: EventType) -> None: 93 char = event.char 94 if char == '': 95 return 96 97 # quit when esc key is pressed 98 if ord(char) == 27: 99 win.quit() 100 101 102 def update_result(event: EventType) -> None: 103 try: 104 expr = input.get() 105 if expr == '': 106 return 107 108 # square brackets are easier to type and are valid math 109 expr = expr.replace('[', '(').replace(']', ')') 110 res = eval(expr) 111 if isinstance(res, int) or isinstance(res, float): 112 output['text'] = '= {:,}'.format(res) 113 else: 114 output['text'] = res 115 except Exception as e: 116 output['text'] = f'= {e}' 117 118 119 win = Tk() 120 win.title('Calculate') 121 input = Entry(font=20, width=35) 122 input.pack(side=LEFT, padx=5) 123 input.bind('<KeyPress>', check_shortcuts) 124 input.bind('<KeyRelease>', update_result) 125 input.focus() 126 output = Label(text='esc quits', font=20) 127 output.pack(side=RIGHT, padx=10, pady=5) 128 win.mainloop()