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 import math
  33 from math import \
  34     acos, acosh, asin, asinh, atan, atan2, atanh, ceil, comb, \
  35     copysign, cos, cosh, degrees, dist, e, erf, erfc, exp, expm1, \
  36     fabs, factorial, floor, fmod, frexp, fsum, gamma, gcd, hypot, inf, \
  37     isclose, isfinite, isinf, isnan, isqrt, lcm, ldexp, lgamma, log, \
  38     log10, log1p, log2, modf, nan, nextafter, perm, pi, pow, prod, \
  39     radians, remainder, sin, sinh, sqrt, tan, tanh, tau, trunc, ulp
  40 try:
  41     from math import cbrt, exp2
  42 except:
  43     pass
  44 
  45 from random import \
  46     betavariate, choice, choices, expovariate, gammavariate, gauss, \
  47     getrandbits, getstate, lognormvariate, normalvariate, paretovariate, \
  48     randbytes, randint, random, randrange, sample, seed, setstate, \
  49     shuffle, triangular, uniform, vonmisesvariate, weibullvariate
  50 
  51 from statistics import \
  52     bisect_left, bisect_right, fmean, \
  53     geometric_mean, harmonic_mean, mean, median, \
  54     median_grouped, median_high, median_low, mode, multimode, pstdev, \
  55     pvariance, quantiles, stdev, variance
  56 try:
  57     from statistics import \
  58         correlation, covariance, linear_regression, mul, reduce
  59 except:
  60     pass
  61 
  62 from tkinter import Tk, Entry, Label, RIGHT, LEFT, EventType
  63 from typing import Callable, Iterable, Any
  64 
  65 
  66 # some convenience aliases to various funcs from the python stdlib
  67 geomean = geometric_mean
  68 harmean = harmonic_mean
  69 sd = stdev
  70 popsd = pstdev
  71 var = variance
  72 popvar = pvariance
  73 randbeta = betavariate
  74 randexp = expovariate
  75 randgamma = gammavariate
  76 randlognorm = lognormvariate
  77 randnorm = normalvariate
  78 randweibull = weibullvariate
  79 
  80 
  81 def check_shortcuts(event: EventType) -> None:
  82     char = event.char
  83     if char == '':
  84         return
  85 
  86     # quit when esc key is pressed
  87     if ord(char) == 27:
  88         win.quit()
  89 
  90 
  91 def update_result(event: EventType) -> None:
  92     try:
  93         expr = input.get()
  94         if expr == '':
  95             return
  96 
  97         # square brackets are easier to type and are valid math
  98         expr = expr.replace('[', '(').replace(']', ')')
  99         output['text'] = '= {:,}'.format(eval(expr))
 100     except Exception as e:
 101         output['text'] = f'= {e}'
 102 
 103 
 104 win = Tk()
 105 win.title('Calculate')
 106 input = Entry(font=20, width=35)
 107 input.pack(side=LEFT, padx=5)
 108 input.bind('<KeyPress>', check_shortcuts)
 109 input.bind('<KeyRelease>', update_result)
 110 input.focus()
 111 output = Label(text='esc quits', font=20)
 112 output.pack(side=RIGHT, padx=10, pady=5)
 113 win.mainloop()