GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix potential usage of None and Unbound variables issues by Avasam · Pull Request #248 · python-xlib/python-xlib

Fix potential usage of None and Unbound variables issues #248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Sign up for GitHub

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Avasam wants to merge 4 commits into python-xlib:master
base: master
Loading
Loading
from Avasam:None-and-Unbound

Uh oh!

There was an error while loading. Please reload this page.

Open

Fix potential usage of None and Unbound variables issues #248

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
4 commits
Select commit Hold shift + click to select a range
46f8a33
Fix potential usage of None and Unbound variables issues - #248
Avasam Oct 31, 2026
682f7f7
Apply batched suggestions from code review
Avasam Oct 31, 2026
2529bf3
Check pack_value once per struct, harden PropertyData, add tests
Avasam Nov 1, 2026
70da09e
Wait on `ReplyRequest._data is None` again
Avasam Nov 1, 2026
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

6 changes: 6 additions & 0 deletions 6 Xlib/XK.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

from Xlib.X import NoSymbol

TYPE_CHECKING = False

def string_to_keysym(keysym):
'''Return the (16 bit) numeric code of keysym.

Expand Down Expand Up @@ -64,7 +66,11 @@ def _load_keysyms_into_XK(mod):

# Always import miscellany and latin1 keysyms
load_keysym_group('miscellany')
if TYPE_CHECKING:
from Xlib.keysymdef.miscellany import *
load_keysym_group('latin1')
if TYPE_CHECKING:
from Xlib.keysymdef.latin1 import *


def keysym_to_string(keysym):
Expand Down
7 changes: 4 additions & 3 deletions 7 Xlib/ext/xinput.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,9 @@ def pack_value(self, val):
# bytes we build a longer array, being careful to maintain native
# byte order across the entire set of values.
if sys.byteorder == 'little':
def fun(val):
mask_seq.insert(0, val)
def fun(__v):
# type: (int) -> None
mask_seq.insert(0, __v)
elif sys.byteorder == 'big':
fun = mask_seq.append
else:
Expand Down Expand Up @@ -378,7 +379,7 @@ def parse_binary_value(self, data, display, length, fmt):
}

class ClassInfoClass(object):

check_value = None
structcode = None

def parse_binary(self, data, display):
Expand Down
45 changes: 25 additions & 20 deletions 45 Xlib/protocol/display.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class Display(object):
extension_major_opcodes = {}
error_classes = error.xerror_class.copy()
event_classes = event.event_class.copy()
resource_classes = {} # type: dict[str, type]

def __init__(self, display = None):
name, protocol, host, displayno, screenno = connect.get_display(display)
Expand Down Expand Up @@ -360,29 +361,32 @@ def send_request(self, request, wait_for_response):
self.request_serial = (self.request_serial + 1) % 65536

self.request_queue.append((request, wait_for_response))
qlen = len(self.request_queue)
# qlen = len(self.request_queue)

self.request_queue_lock.release()

# if qlen > 10:
# self.flush()
# if qlen > 10:
# self.flush()

def close_internal(self, whom):
# Clear out data structures
self.request_queue = None
self.sent_requests = None
self.event_queue = None
self.data_send = None
self.data_recv = None
self.request_queue = []
self.sent_requests = []
self.event_queue = []
self.data_send = b''
self.data_recv = b''

# Close the connection
self.socket.close()

# Set a connection closed indicator
err = error.ConnectionClosedError(whom)
self.socket_error_lock.acquire()
self.socket_error = error.ConnectionClosedError(whom)
self.socket_error = err
self.socket_error_lock.release()

return err


def send_and_recv(self, flush = False, event = False, request = None, recv = False):
"""send_and_recv(flush = None, event = None, request = None, recv = None)
Expand Down Expand Up @@ -582,8 +586,7 @@ def send_and_recv(self, flush = False, event = False, request = None, recv = Fal
try:
i = self.socket.send(self.data_send)
except socket.error as err:
self.close_internal('server: %s' % err)
raise self.socket_error
raise self.close_internal('server: %s' % err)

self.data_send = self.data_send[i:]
self.data_sent_bytes = self.data_sent_bytes + i
Expand All @@ -600,13 +603,11 @@ def send_and_recv(self, flush = False, event = False, request = None, recv = Fal
count = max(self.recv_buffer_size, count)
bytes_recv = self.socket.recv(count)
except socket.error as err:
self.close_internal('server: %s' % err)
raise self.socket_error
raise self.close_internal('server: %s' % err)

if not bytes_recv:
# Clear up, set a connection closed indicator and raise it
self.close_internal('server')
raise self.socket_error
raise self.close_internal('server')

self.data_recv = bytes(self.data_recv) + bytes_recv
gotreq = self.parse_response(request)
Expand Down Expand Up @@ -690,6 +691,7 @@ def parse_response(self, request):

# Parse ordinary server response
gotreq = False
rtype = None
while True:
if self.data_recv:
# Check the first byte to find out what kind of response it is
Expand All @@ -703,23 +705,23 @@ def parse_response(self, request):
if rtype == 1:
gotreq = self.parse_request_response(request) or gotreq
continue
elif rtype & 0x7f == ge.GenericEventCode:
elif rtype and (rtype & 0x7f == ge.GenericEventCode):
self.parse_event_response(rtype)
continue
else:
raise AssertionError(rtype)

# Every response is at least 32 bytes long, so don't bother
# until we have received that much
if len(self.data_recv) < 32:
if len(self.data_recv) < 32 or rtype is None:
return gotreq

# Error response
if rtype == 0:
gotreq = self.parse_error_response(request) or gotreq

# Request response or generic event.
elif rtype == 1 or rtype & 0x7f == ge.GenericEventCode:
elif rtype == 1 or (rtype & 0x7f == ge.GenericEventCode):
# Set reply length, and loop around to see if
# we have got the full response
rlen = int(struct.unpack('=L', self.data_recv[4:8])[0])
Expand Down Expand Up @@ -811,10 +813,12 @@ def parse_request_response(self, request):


def parse_event_response(self, etype):
# type: (int) -> None
# Skip bit 8, that is set if this event came from an SendEvent
etype = etype & 0x7f
is_generic_event_code = etype == ge.GenericEventCode

if etype == ge.GenericEventCode:
if is_generic_event_code:
length = self.recv_packet_len
else:
length = 32
Expand All @@ -832,7 +836,7 @@ def parse_event_response(self, etype):

e = estruct(display = self, binarydata = self.data_recv[:length])

if etype == ge.GenericEventCode:
if is_generic_event_code:
self.recv_packet_len = 0

self.data_recv = bytesview(self.data_recv, length)
Expand Down Expand Up @@ -1022,6 +1026,7 @@ def parse_connection_setup(self):


class ConnectionSetupRequest(rq.GetAttrData):
_serial = None # type: int | None
_request = rq.Struct( rq.Set('byte_order', 1, (0x42, 0x6c)),
rq.Pad(1),
rq.Card16('protocol_major'),
Expand Down
53 changes: 40 additions & 13 deletions 53 Xlib/protocol/rq.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
import struct
from array import array

TYPE_CHECKING = False

if TYPE_CHECKING:
from typing import Any, Callable

# Python 2/3 compatibility.
from six import PY3, binary_type, byte2int, indexbytes, iterbytes

Expand Down Expand Up @@ -109,8 +114,9 @@ class Field(object):
f.parse_binary_value() instead. See its documentation string for
details.
"""
name = None
name = ""
default = None
pack_value = None # type: Callable[..., tuple[Any, int | None, int | None]] | None

structcode = None
structvalues = 0
Expand Down Expand Up @@ -301,8 +307,8 @@ def check_value(self, value):
return value

def parse_value(self, value, display):
# if not display:
# return value
if not display:
return value
if value in self.codes:
return value

Expand Down Expand Up @@ -648,23 +654,27 @@ class PropertyData(ValueField):
structcode = None

def parse_binary_value(self, data, display, length, format):
# Format 0 means the property does not exist, so there is no data
if format == 0:
return None, data

if format not in (8, 16, 32):
raise BadDataError('Invalid property data format {0}'.format(format))

if length is None:
length = len(data) // (format // 8)
else:
length = int(length)

if format == 0:
ret = None

elif format == 8:
if format == 8:
ret = (8, data[:length])
data = data[length + ((4 - length % 4) % 4):]

elif format == 16:
ret = (16, array(array_unsigned_codes[2], data[:2 * length]))
data = data[2 * (length + length % 2):]

elif format == 32:
else:
ret = (32, array(array_unsigned_codes[4], data[:4 * length]))
data = data[4 * length:]

Expand Down Expand Up @@ -892,8 +902,8 @@ def __init__(self, class_name):
self.check_value = None

def parse_value(self, value, display):
# if not display:
# return value
if not display:
return value
c = display.get_resource_class(self.class_name)
if c:
return c(display, value)
Expand Down Expand Up @@ -937,6 +947,9 @@ class Field. The fields of a structure are given as arguments
object to make conversion as fast as possible. They are
generated the first time the methods are called.
"""
name = ""
check_value = None # type: Callable[[Any], Any] | None
keyword_args = False

def __init__(self, *fields):
self.fields = fields
Expand Down Expand Up @@ -967,6 +980,8 @@ def __init__(self, *fields):
self.var_fields.append(f)

self.static_size = struct.calcsize(self.static_codes)
# Parse-only fields have no pack_value, so only to_binary refuses them
self._unpackable_fields = [f for f in self.var_fields if f.pack_value is None]
if self.var_fields:
self.structcode = None
self.structvalues = 0
Expand Down Expand Up @@ -1013,6 +1028,11 @@ def to_binary(self, *varargs, **keys):
lengths = {}
formats = {}

if self._unpackable_fields:
raise RuntimeError('No pack_value provided for {0}'.format(
', '.join('{0} ({1})'.format(f.name, type(f).__name__)
for f in self._unpackable_fields)))

for f in self.var_fields:
if f.keyword_args:
v, l, fm = f.pack_value(field_args[f.name], keys)
Expand Down Expand Up @@ -1287,6 +1307,8 @@ class TextElements16(TextElements8):


class GetAttrData(object):
# GetAttrData classes get their attributes dynamically
# TODO: Complete all classes inheriting from GetAttrData
def __getattr__(self, attr):
try:
if self._data:
Expand Down Expand Up @@ -1341,6 +1363,7 @@ def __eq__(self, other):


class Request(object):
_request = None # type: Struct
def __init__(self, display, onerror = None, *args, **keys):
self._errorhandler = onerror
self._binary = self._request.to_binary(*args, **keys)
Expand All @@ -1354,6 +1377,7 @@ def _set_error(self, error):
return 0

class ReplyRequest(GetAttrData):
_request = None # type: Struct
def __init__(self, display, defer = False, *args, **keys):
self._display = display
self._binary = self._request.to_binary(*args, **keys)
Expand All @@ -1371,13 +1395,15 @@ def reply(self):
# Send request and wait for reply if we hasn't
# already got one. This means that reply() can safely
# be called more than one time.
# _display is cleared once a reply or error has been received
display = self._display

self._response_lock.acquire()
while self._data is None and self._error is None:
self._display.send_recv_lock.acquire()
while display is not None and self._data is None and self._error is None:
display.send_recv_lock.acquire()
self._response_lock.release()

self._display.send_and_recv(request = self._serial)
display.send_and_recv(request = self._serial)
self._response_lock.acquire()

self._response_lock.release()
Expand All @@ -1403,6 +1429,7 @@ def __repr__(self):


class Event(GetAttrData):
_fields = None # type: Struct
def __init__(self, binarydata = None, display = None,
**keys):
if binarydata:
Expand Down
2 changes: 1 addition & 1 deletion 2 Xlib/xobject/colormap.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def free(self, onerror = None):

self.display.free_resource_id(self.id)

def copy_colormap_and_free(self, scr_cmap):
def copy_colormap_and_free(self, src_cmap):
mid = self.display.allocate_resource_id()
request.CopyColormapAndFree(display = self.display,
mid = mid,
Expand Down
Loading
Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.