Skip to content

Commit

Permalink
7.3.2
Browse files Browse the repository at this point in the history
applied pylint checking
  • Loading branch information
quantum-leaps committed Dec 20, 2023
1 parent fc734c7 commit 0579723
Show file tree
Hide file tree
Showing 7 changed files with 730 additions and 722 deletions.
179 changes: 102 additions & 77 deletions qcalc/qcalc.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env python

#=============================================================================
# QCalc programmer's Calculator
# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
Expand All @@ -23,101 +25,113 @@
# <[email protected]>
#=============================================================================
##
# @date Last updated on: 2022-01-27
# @version Last updated for version: 7.0.0
# @date Last updated on: 2023-12-18
# @version Last updated for version: 7.3.2
#
# @file
# @brief QCalc programmer's Calculator
# @ingroup qtools

# pylint: disable=broad-except
# pylint: disable=eval-used


'''
"qcalc" is a powerful, cross-platform calculator specifically designed for
embedded systems programmers. The calculator accepts whole expressions in
the **C-syntax** and displays results simultaneously in decimal, hexadecimal,
and binary without the need to explicitly convert the result to these bases.
'''

import os
import sys
import traceback

from math import *
from platform import python_version
from sys import argv

# NOTE: the following wildcard import from math is needed
# for user expressions.
#
# pylint: disable=wildcard-import
# pylint: disable=unused-wildcard-import
# pylint: disable=redefined-builtin
from math import *

# current version of QCalc
VERSION = 732

# the 'ans' global variable
ans = 0

class QCalc:
## current version of QCalc
VERSION = 700

@staticmethod
def _print(result):
# the 'ans' global variable
global ans
ans = result

if isinstance(ans, int):
# outside the 64-bit range?
if ans < -0xFFFFFFFFFFFFFFFF or 0xFFFFFFFFFFFFFFFF < ans:
print("\x1b[41m\x1b[1;37m! out of range\x1b[0m")
return

#inside the 32-bit range?
if -0xFFFFFFFF < ans and ans <= 0xFFFFFFFF:
# use 32-bit unsigned arithmetic...
u32 = ans & 0xFFFFFFFF
u16_0 = u32 & 0xFFFF
u16_1 = (u32 >> 16) & 0xFFFF
u8_0 = u32 & 0xFF
u8_1 = (u32 >> 8) & 0xFF
u8_2 = (u32 >> 16) & 0xFF
u8_3 = (u32 >> 24) & 0xFF
print("= {0:d} |".format(ans),
"0x{0:04X}'{1:04X} |".format(u16_1, u16_0),
"0b{0:08b}'{1:08b}'{2:08b}'{3:08b}".format(
u8_3, u8_2, u8_1, u8_0))
else:
# use 64-bit unsigned arithmetic...
u64 = ans & 0xFFFFFFFFFFFFFFFF
u16_0 = u64 & 0xFFFF
u16_1 = (u64 >> 16) & 0xFFFF
u16_2 = (u64 >> 32) & 0xFFFF
u16_3 = (u64 >> 48) & 0xFFFF
u8_0 = u64 & 0xFF
u8_1 = (u64 >> 8) & 0xFF
u8_2 = (u64 >> 16) & 0xFF
u8_3 = (u64 >> 24) & 0xFF
u8_4 = (u64 >> 32) & 0xFF
u8_5 = (u64 >> 40) & 0xFF
u8_6 = (u64 >> 48) & 0xFF
u8_7 = (u64 >> 56) & 0xFF
print("= {0:d} |".format(ans),
"0x{0:04X}'{1:04X}'{2:04X}'{3:04X}".format(
u16_3, u16_2, u16_1, u16_0))
print("= 0b{0:08b}'{1:08b}'{2:08b}'{3:08b}"
"'{4:08b}'{5:08b}'{6:08b}'{7:08b}".format(
u8_7, u8_6, u8_5, u8_4, u8_3, u8_2, u8_1, u8_0))
ans = {}

def display(result):
'''
Display result of computation in decimal, hexadecimal, and binary.
Also, handle the 32-bit and 64-bit cases.
'''

# pylint: disable=global-statement
global ans
ans = result

if isinstance(ans, int):
# outside the 64-bit range?
if ans < -0xFFFFFFFFFFFFFFFF or 0xFFFFFFFFFFFFFFFF < ans:
print("\x1b[41m\x1b[1;37m! out of range\x1b[0m")
return

#inside the 32-bit range?
if -0xFFFFFFFF < ans <= 0xFFFFFFFF:
# use 32-bit unsigned arithmetic...
u32 = ans & 0xFFFFFFFF
u16_0 = u32 & 0xFFFF
u16_1 = (u32 >> 16) & 0xFFFF
u8_0 = u32 & 0xFF
u8_1 = (u32 >> 8) & 0xFF
u8_2 = (u32 >> 16) & 0xFF
u8_3 = (u32 >> 24) & 0xFF
print(f"= {ans:d} |",
f"0x{u16_1:04X}'{u16_0:04X} |",
f"0b{u8_3:08b}'{u8_2:08b}'{u8_1:08b}'{u8_0:08b}", end="")
else:
print("=", ans)
# use 64-bit unsigned arithmetic...
u64 = ans & 0xFFFFFFFFFFFFFFFF
u16_0 = u64 & 0xFFFF
u16_1 = (u64 >> 16) & 0xFFFF
u16_2 = (u64 >> 32) & 0xFFFF
u16_3 = (u64 >> 48) & 0xFFFF
u8_0 = u64 & 0xFF
u8_1 = (u64 >> 8) & 0xFF
u8_2 = (u64 >> 16) & 0xFF
u8_3 = (u64 >> 24) & 0xFF
u8_4 = (u64 >> 32) & 0xFF
u8_5 = (u64 >> 40) & 0xFF
u8_6 = (u64 >> 48) & 0xFF
u8_7 = (u64 >> 56) & 0xFF
print(f"= {ans:d} |",
f"0x{u16_3:04X}'{u16_2:04X}'{u16_1:04X}'{u16_0:04X}")
print(f"= 0b{u8_7:08b}'{u8_6:08b}'{u8_5:08b}'{u8_4:08b}"\
f"'{u8_3:08b}'{u8_2:08b}'{u8_1:08b}'{u8_0:08b}", end="")
else:
print("=", ans)

#=============================================================================
# main entry point to QCalc
def main():
if os.name == "nt":
os.system("color")

print("QCalc Programmer's Calculator {0:d}.{1:d}.{2:d} " \
"running on Python {3}".format(
QCalc.VERSION//100,
(QCalc.VERSION//10) % 10,
QCalc.VERSION % 10,
python_version()))
print("(c) 2005-2022 Quantum Leaps, www.state-machine.com\n")

'''
Main entry point to QCalc. Process command-line parameters
and handle separately "batch" and "interactive" modes.
'''
# "batch mode": expression provided in command-line arguments
if len(argv) > 1:
expr = "".join(argv[1:])
if len(sys.argv) > 1:
expr = "".join(sys.argv[1:])
print(expr)
try:
result = eval(expr)
except:
except Exception:
traceback.print_exc(2)
else:
QCalc._print(result)
display(result)
return

# "interactive mode": expressions provided as user input
Expand All @@ -126,16 +140,27 @@ def main():
if expr:
try:
result = eval(expr)
except:
except Exception:
traceback.print_exc(2)
else:
print("\x1b[47m\x1b[30m", end = "")
QCalc._print(result)
print("\x1b[0m", end = "")
display(result)
print("\x1b[0m")
else:
break


#=============================================================================
if __name__ == "__main__":
main()
if os.name == "nt":
os.system("color")

print(f"\nQCalc programmer's calculator "\
f"{VERSION//100}.{(VERSION//10) % 10}."\
f"{VERSION % 10} running on Python {python_version()}")
print("Copyright (c) 2005-2023 Quantum Leaps, www.state-machine.com")
if sys.version_info >= (3,6):
main()
else:
print("\nERROR: QCalc requires Python 3.6 or newer")
sys.exit(-1)
2 changes: 1 addition & 1 deletion qcalc/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

setup(
name="qcalc",
version="7.0.0",
version="7.3.2",
author="Quantum Leaps",
author_email="[email protected]",
description="qcalc programmer's calculator",
Expand Down
86 changes: 38 additions & 48 deletions qspy/qspy_exit.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env python

#=============================================================================
# QUTest Python scripting support
# qspy_exit utility
# Copyright (C) 2005 Quantum Leaps, LLC. All rights reserved.
#
# SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial
Expand All @@ -22,31 +24,27 @@
# <www.state-machine.com>
# <[email protected]>
#=============================================================================
##
# @date Last updated on: 2023-12-13
# @version Last updated for version: 7.3.1
#
# @file
# @brief QUTest Python scripting support (implementation)
# @ingroup qutest

# pylint: disable=missing-module-docstring,
# pylint: disable=missing-class-docstring,
# pylint: disable=missing-function-docstring
# pylint: disable=broad-except

from platform import python_version

import argparse
import socket
import struct
import sys
import os
if os.name == "nt":
import msvcrt
else:
import select

from platform import python_version

#=============================================================================
# Helper class for communication with the QSpy front-end
#
class QSpy:
VERSION = 731

# public class constants
VERSION = 732
TIMEOUT = 1.000 # timeout value [seconds]

# private class variables...
_sock = None
Expand All @@ -55,9 +53,6 @@ class QSpy:
_host_udp = ["localhost", 7701] # list, to be converted to a tuple
_local_port = 0 # let the OS decide the best local port

# timeout value [seconds]
_TOUT = 1.000

# packets to QSpy only...
_QSPY_ATTACH = 128
_QSPY_DETACH = 129
Expand All @@ -69,68 +64,55 @@ class QSpy:
_QSPY_CLEAR_SCREEN = 140
_QSPY_SHOW_NOTE = 141

# packets to QSpy to be "massaged" and forwarded to the Target...
_QSPY_SEND_EVENT = 135
_QSPY_SEND_AO_FILTER = 136
_QSPY_SEND_CURR_OBJ = 137
_QSPY_SEND_COMMAND = 138
_QSPY_SEND_TEST_PROBE = 139

@staticmethod
def _init():
# Create socket
QSpy._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
QSpy._sock.settimeout(QSpy._TOUT) # timeout for blocking socket
QSpy._sock.settimeout(QSpy.TIMEOUT) # timeout for blocking socket
#bufsize = QSpy._sock.getsockopt(socket.SOL_UDP, socket.SO_RCVBUF)
#print("SO_RCVBUF ", bufsize)
try:
QSpy._sock.bind(("0.0.0.0", QSpy._local_port))
#print("bind: ", ("0.0.0.0", QSpy._local_port))
except:
messagebox.showerror("UDP Socket Error",
"Can't bind the UDP socket\nto the specified local_host")
QSpyView._gui.destroy()
return -1
except Exception:
print("UDP Socket Error"\
"Can't bind the UDP socket\nto the specified local_host")
sys.exit(-1)
return 0

@staticmethod
def _sendTo(packet, str=None):
def send_to(packet, payload=None):
tx_packet = bytearray([QSpy._tx_seq])
tx_packet.extend(packet)
if str is not None:
tx_packet.extend(bytes(str, "utf-8"))
if payload is not None:
tx_packet.extend(bytes(payload, "utf-8"))
tx_packet.extend(b"\0") # zero-terminate
QSpy._sock.sendto(tx_packet, QSpy._host_udp)
QSpy._tx_seq = (QSpy._tx_seq + 1) & 0xFF
#print("sendTo", QSpy._tx_seq)

#=============================================================================
# main entry point to QUTest
# main entry point to qspy_exit
def main():
# pylint: disable=protected-access

# parse command-line arguments...
parser = argparse.ArgumentParser(
prog="python qspy_exit.py",
description="QSPY-exit",
epilog="More info: https://www.state-machine.com/qspy.html#qspy_exit")
parser.add_argument('-v', '--version',
action='version',
version="QSPY-exit %d.%d.%d on Python %s"%(
QSpy.VERSION//100, (QSpy.VERSION//10) % 10,
QSpy.VERSION % 10,
python_version()),
version=f"QSPY-exit {QSpy.VERSION//100}."\
f"{(QSpy.VERSION//10) % 10}.{QSpy.VERSION % 10} "\
f"on Python {python_version()}",
help='Display QSPY-exit version')

parser.add_argument('-q', '--qspy', nargs='?', default='', const='',
help="optional qspy host, [:ud_port]")
args = parser.parse_args()
#print(args)

print("\nQSPY-exit %d.%d.%d running on Python %s"%(
QSpy.VERSION//100,
(QSpy.VERSION//10) % 10,
QSpy.VERSION % 10, python_version()))
print("Copyright (c) 2005-2023 Quantum Leaps, www.state-machine.com")

# process command-line argumens...
if args.qspy != '':
qspy_conf = args.qspy.split(":")
Expand All @@ -150,10 +132,18 @@ def main():
if err:
return sys.exit(err)

QSpy._sendTo(struct.pack("<BB", QSpy._QSPY_DETACH, 1))
QSpy.send_to(struct.pack("<BB", QSpy._QSPY_DETACH, 1))

return 0 # report to the caller (e.g., make)

#=============================================================================
if __name__ == "__main__":
main()
print(f"\nQSPY-exit "\
f"{QSpy.VERSION//100}.{(QSpy.VERSION//10) % 10}."\
f"{QSpy.VERSION % 10} running on Python {python_version()}")
print("Copyright (c) 2005-2023 Quantum Leaps, www.state-machine.com")
if sys.version_info >= (3,6):
main()
else:
print("\nERROR: QSPY-exit requires Python 3.6 or newer")
sys.exit(-1)
Loading

0 comments on commit 0579723

Please sign in to comment.