Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
fbebf77
chore: extend ruff scope
nijel Feb 5, 2026
c7084d4
chore: use asserts directly for pytest
nijel Feb 5, 2026
838c09f
chore: fix docstrings
nijel Feb 5, 2026
9887076
chore: update ruff config
nijel Feb 5, 2026
f9ee662
chore: simplify - operation
nijel Feb 5, 2026
0028ba8
chore: add simple type annotations
nijel Feb 5, 2026
c460656
chore: directly return result
nijel Feb 5, 2026
f71e497
chore: use list/dict directly
nijel Feb 5, 2026
79f473d
chore: use ternary operator
nijel Feb 5, 2026
64978c1
chore: update list using extend
nijel Feb 5, 2026
f6aea58
chore: use pathlib helpers to write files
nijel Feb 5, 2026
9ddd22b
chore: use maxsplit
nijel Feb 5, 2026
1ab2e14
chore: use raw string for regex
nijel Feb 5, 2026
e222b4c
chore: avoid concatenation on one line
nijel Feb 5, 2026
e9387c9
chore: sort imports
nijel Feb 5, 2026
ec0105c
chore: Use a set literal when testing for membership
nijel Feb 5, 2026
631895d
chore: update ruff formatting
nijel Feb 5, 2026
2587b6b
chore: use f-string instead for format
nijel Feb 5, 2026
02f9339
chore: annotate S603
nijel Feb 5, 2026
ade0a44
chore: scope assert test
nijel Feb 5, 2026
9d4fab3
chore: simplify exception raising
nijel Feb 5, 2026
46df1c9
chore: scope PYI056
nijel Feb 5, 2026
1143563
chore: use context to catch exceptions in tests
nijel Feb 5, 2026
ef386a0
chore: use pytest.skip
nijel Feb 5, 2026
f3dbcb4
chore: define encoding on files
nijel Feb 5, 2026
ea47cef
chore: avoid using global variable to track state
nijel Feb 5, 2026
caaf285
chore: avoid redefining argument with the local name
nijel Feb 5, 2026
6395a72
chore: annotate too many nested blocks
nijel Feb 5, 2026
1ae2dde
chore: simplify empty string conditions
nijel Feb 5, 2026
eeb48ef
chore: use pathlib to read file content
nijel Feb 5, 2026
a9780bc
chore: document todo
nijel Feb 5, 2026
ad0644e
chore: remove no longer needed overrides
nijel Feb 5, 2026
687c939
chore: improve docstrings
nijel Feb 5, 2026
be3daa6
chore: fix docstring formatting
nijel Feb 5, 2026
21b700e
chore: improve docstrings
nijel Feb 5, 2026
8d8de91
chore: add missing file header
nijel Feb 5, 2026
b31f1b2
chore: annotate BLE001
nijel Feb 5, 2026
9b6378c
chore: avoid overwriting loop variables
nijel Feb 5, 2026
217d3ec
fix: assert specific exception
nijel Feb 5, 2026
793a215
fix: improve async waiting for thread
nijel Feb 5, 2026
68de586
chore: apply review feedback
nijel Feb 5, 2026
c14abf7
chore: ignore uv lock file
nijel Feb 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ python_gammu.egg-info/
.coverage
/.cache/
_codeql_detected_source_root
/uv.lock
20 changes: 0 additions & 20 deletions examples/__init__.py

This file was deleted.

2 changes: 1 addition & 1 deletion examples/addcontacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import gammu


def main():
def main() -> None:
if len(sys.argv) != 3:
print("This requires two parameters: memory_type and backup file (eg. vcard)!")
sys.exit(1)
Expand Down
6 changes: 3 additions & 3 deletions examples/addfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@


import os
import pathlib
import sys

import gammu


def main():
def main() -> None:
if len(sys.argv) != 3:
print("This requires two parameters: file to upload and path!")
sys.exit(1)

with open(sys.argv[1], "rb") as handle:
data = handle.read()
data = pathlib.Path(sys.argv[1]).read_bytes()
Comment thread Dismissed

state_machine = gammu.StateMachine()
state_machine.ReadConfig()
Expand Down
30 changes: 15 additions & 15 deletions examples/async.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
python-gammu - Phone communication library
Gammu asynchronous wrapper example with asyncio. This allows your application to care
only about handling received data and not about phone communication
details.
Gammu asynchronous wrapper example with asyncio.

This allows your application to care only about handling received data and not
about phone communication details.
"""

import asyncio
Expand All @@ -32,7 +32,7 @@
import gammu.asyncworker


async def send_message_async(state_machine, number, message):
async def send_message_async(state_machine, number, message) -> None:
smsinfo = {
"Class": -1,
"Unicode": False,
Expand All @@ -41,15 +41,15 @@ async def send_message_async(state_machine, number, message):
# Encode messages
encoded = gammu.EncodeSMS(smsinfo)
# Send messages
for message in encoded:
for encoded_message in encoded:
# Fill in numbers
message["SMSC"] = {"Location": 1}
message["Number"] = number
encoded_message["SMSC"] = {"Location": 1}
encoded_message["Number"] = number
# Actually send the message
await state_machine.send_sms_async(message)
await state_machine.send_sms_async(encoded_message)


async def get_network_info(worker):
async def get_network_info(worker) -> None:
info = await worker.get_network_info_async()
print("NetworkName:", info["NetworkName"])

Expand All @@ -67,7 +67,7 @@ async def get_network_info(worker):
print(" LAC:", info["LAC"])


async def get_info(worker):
async def get_info(worker) -> None:
print("Phone information:")
manufacturer = await worker.get_manufacturer_async()
print("{:<15}: {}".format("Manufacturer", manufacturer))
Expand All @@ -79,11 +79,11 @@ async def get_info(worker):
print("{:<15}: {}".format("Firmware", firmware[0]))


async def main():
async def main() -> None:
gammu.SetDebugFile(sys.stderr)
gammu.SetDebugLevel("textall")

config = dict(Device="/dev/ttyS6", Connection="at")
config = {"Device": "/dev/ttyS6", "Connection": "at"}
worker = gammu.asyncworker.GammuAsyncWorker()
worker.configure(config)

Expand All @@ -102,12 +102,12 @@ async def main():
try:
signal = await worker.get_signal_quality_async()
print("Signal is at {:d}%".format(signal["SignalPercent"]))
except Exception as e:
except Exception as e: # noqa: BLE001
print(f"Exception reading signal: {e}")

await asyncio.sleep(10)

except Exception as e:
except Exception as e: # noqa: BLE001
print("Exception:")
print(e)

Expand Down
2 changes: 1 addition & 1 deletion examples/debugging.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import gammu


def main():
def main() -> None:
# Global debug level
gammu.SetDebugFile(sys.stderr)
gammu.SetDebugLevel("textall")
Expand Down
6 changes: 3 additions & 3 deletions examples/doc-exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
import gammu.exception


def main():
def main() -> None:
for exc in sorted(gammu.exception.__all__):
print(f".. exception:: gammu.{exc}")
print()
doc = getattr(gammu.exception, exc).__doc__
for doc in doc.splitlines():
print(f" {doc}")
for line in doc.splitlines():
print(f" {line}")
print()


Expand Down
32 changes: 17 additions & 15 deletions examples/dummy_phone.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,18 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
"""
python-gammu - Test script to test several Gammu operations
(usually using dummy driver, but it depends on config)
Dummy driver example.

Test script to test several Gammu operations (usually using dummy driver, but
it depends on config).
"""

import sys

import gammu


def get_all_memory(state_machine, memory_type):
def get_all_memory(state_machine, memory_type) -> None:
status = state_machine.GetMemoryStatus(Type=memory_type)

remain = status["Used"]
Expand All @@ -44,7 +46,7 @@ def get_all_memory(state_machine, memory_type):
entry = state_machine.GetNextMemory(
Location=entry["Location"], Type=memory_type
)
remain = remain - 1
remain -= 1

print()
print("{:<15}: {:d}".format("Location", entry["Location"]))
Expand All @@ -55,7 +57,7 @@ def get_all_memory(state_machine, memory_type):
print("{:<15}: {}".format(v["Type"], v["Value"]))


def get_all_calendar(state_machine):
def get_all_calendar(state_machine) -> None:
status = state_machine.GetCalendarStatus()

remain = status["Used"]
Expand All @@ -68,7 +70,7 @@ def get_all_calendar(state_machine):
start = False
else:
entry = state_machine.GetNextCalendar(Location=entry["Location"])
remain = remain - 1
remain -= 1

print()
print("{:<20}: {:d}".format("Location", entry["Location"]))
Expand All @@ -77,7 +79,7 @@ def get_all_calendar(state_machine):
print("{:<20}: {}".format(v["Type"], v["Value"]))


def get_battery_status(state_machine):
def get_battery_status(state_machine) -> None:
status = state_machine.GetBatteryCharge()

for x in status:
Expand All @@ -98,12 +100,12 @@ def get_all_sms(state_machine):
start = False
else:
sms = state_machine.GetNextSMS(Location=sms[0]["Location"], Folder=0)
remain = remain - len(sms)
remain -= len(sms)

return sms


def print_sms_header(message, folders):
def print_sms_header(message, folders) -> None:
print()
print("{:<15}: {}".format("Number", message["Number"]))
print("{:<15}: {}".format("Date", message["DateTime"]))
Expand All @@ -119,16 +121,16 @@ def print_sms_header(message, folders):
print("{:<15}: {}".format("Validity", message["SMSC"]["Validity"]))


def print_all_sms(sms, folders):
def print_all_sms(sms, folders) -> None:
for m in sms:
print_sms_header(m, folders)
print("\n{}".format(m["Text"]))


def link_all_sms(sms, folders):
def link_all_sms(sms, folders) -> None:
data = gammu.LinkSMS([[msg] for msg in sms])

for x in data:
for x in data: # noqa: PLR1702
v = gammu.DecodeSMS(x)

m = x[0]
Expand All @@ -155,7 +157,7 @@ def link_all_sms(sms, folders):
print()


def get_all_todo(state_machine):
def get_all_todo(state_machine) -> None:
status = state_machine.GetToDoStatus()

remain = status["Used"]
Expand All @@ -168,7 +170,7 @@ def get_all_todo(state_machine):
start = False
else:
entry = state_machine.GetNextToDo(Location=entry["Location"])
remain = remain - 1
remain -= 1

print()
print("{:<15}: {:d}".format("Location", entry["Location"]))
Expand All @@ -191,7 +193,7 @@ def get_set_date_time(state_machine):
return dt


def main():
def main() -> None:
if len(sys.argv) != 2:
print("This requires one parameter with location of config file!")
sys.exit(1)
Expand Down
30 changes: 16 additions & 14 deletions examples/filesystem_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
"""
Filesystem testing.

This file should provide me with a test frame for the filesystem
functions. It can't be run automatically, but you should be able
to decide, whether the output looks sensible
to decide, whether the output looks sensible.

BEWARE - the test WILL TOUCH AND WRITE FILESYSTEM!!

Expand Down Expand Up @@ -51,7 +53,7 @@
import gammu


def main():
def main() -> None: # noqa: PLR0912, PLR0915, C901
parser = argparse.ArgumentParser(usage="usage: %(prog)s [options]")

parser.add_argument(
Expand Down Expand Up @@ -182,13 +184,13 @@ def main():
else:
attribute = ""
if file_f["Protected"]:
attribute = attribute + "P"
attribute += "P"
if file_f["ReadOnly"]:
attribute = attribute + "R"
attribute += "R"
if file_f["Hidden"]:
attribute = attribute + "H"
attribute += "H"
if file_f["System"]:
attribute = attribute + "S"
attribute += "S"
print(
"ID: "
+ file_f["ID_FullName"]
Expand Down Expand Up @@ -234,13 +236,13 @@ def main():
else:
attribute = ""
if file_f["Protected"]:
attribute = attribute + "P"
attribute += "P"
if file_f["ReadOnly"]:
attribute = attribute + "R"
attribute += "R"
if file_f["Hidden"]:
attribute = attribute + "H"
attribute += "H"
if file_f["System"]:
attribute = attribute + "S"
attribute += "S"
print(
"ID: "
+ file_f["ID_FullName"]
Expand Down Expand Up @@ -290,13 +292,13 @@ def main():
else:
attribute = ""
if file_f["Protected"]:
attribute = attribute + "P"
attribute += "P"
if file_f["ReadOnly"]:
attribute = attribute + "R"
attribute += "R"
if file_f["Hidden"]:
attribute = attribute + "H"
attribute += "H"
if file_f["System"]:
attribute = attribute + "S"
attribute += "S"
print(
"ID: "
+ file_f["ID_FullName"]
Expand Down
4 changes: 2 additions & 2 deletions examples/getallcalendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
"""Example for reading calendar from phone"""
"""Example for reading calendar from phone."""

import gammu

Expand All @@ -46,7 +46,7 @@
start = False
else:
entry = state_machine.GetNextCalendar(Location=entry["Location"])
remain = remain - 1
remain -= 1

# Display it
print()
Expand Down
4 changes: 2 additions & 2 deletions examples/getallmemory.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import gammu


def main():
def main() -> None:
state_machine = gammu.StateMachine()
state_machine.ReadConfig()
state_machine.Init()
Expand All @@ -51,7 +51,7 @@ def main():
entry = state_machine.GetNextMemory(
Location=entry["Location"], Type=memory_type
)
remain = remain - 1
remain -= 1

print()
print("{:<15}: {:d}".format("Location", entry["Location"]))
Expand Down
Loading
Loading