This file is indexed.

/usr/share/pyshared/sqlobject/include/pydispatch/dispatcher.py is in python-sqlobject 0.12.4-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
"""Multiple-producer-multiple-consumer signal-dispatching

dispatcher is the core of the PyDispatcher system,
providing the primary API and the core logic for the
system.

Module attributes of note:

	Any -- Singleton used to signal either "Any Sender" or
		"Any Signal".  See documentation of the _Any class.
	Anonymous -- Singleton used to signal "Anonymous Sender"
		See documentation of the _Anonymous class.

Internal attributes:
	WEAKREF_TYPES -- tuple of types/classes which represent
		weak references to receivers, and thus must be de-
		referenced on retrieval to retrieve the callable
		object
	connections -- { senderkey (id) : { signal : [receivers...]}}
	senders -- { senderkey (id) : weakref(sender) }
		used for cleaning up sender references on sender
		deletion
	sendersBack -- { receiverkey (id) : [senderkey (id)...] }
		used for cleaning up receiver references on receiver
		deletion, (considerably speeds up the cleanup process
		vs. the original code.)
"""
from __future__ import generators
import types, weakref
import saferef, robustapply, errors

__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id: dispatcher.py,v 1.9 2005/09/17 04:55:57 mcfletch Exp $"
__version__ = "$Revision: 1.9 $"[11:-2]

try:
	True
except NameError:
	True = 1==1
	False = 1==0

class _Parameter:
	"""Used to represent default parameter values."""
	def __repr__(self):
		return self.__class__.__name__

class _Any(_Parameter):
	"""Singleton used to signal either "Any Sender" or "Any Signal"

	The Any object can be used with connect, disconnect,
	send, or sendExact to signal that the parameter given
	Any should react to all senders/signals, not just
	a particular sender/signal.
	"""
Any = _Any()

class _Anonymous(_Parameter):
	"""Singleton used to signal "Anonymous Sender"

	The Anonymous object is used to signal that the sender
	of a message is not specified (as distinct from being
	"any sender").  Registering callbacks for Anonymous
	will only receive messages sent without senders.  Sending
	with anonymous will only send messages to those receivers
	registered for Any or Anonymous.

	Note:
		The default sender for connect is Any, while the
		default sender for send is Anonymous.  This has
		the effect that if you do not specify any senders
		in either function then all messages are routed
		as though there was a single sender (Anonymous)
		being used everywhere.
	"""
Anonymous = _Anonymous()

WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref)

connections = {}
senders = {}
sendersBack = {}


def connect(receiver, signal=Any, sender=Any, weak=True):
	"""Connect receiver to sender for signal

	receiver -- a callable Python object which is to receive
		messages/signals/events.  Receivers must be hashable
		objects.

		if weak is True, then receiver must be weak-referencable
		(more precisely saferef.safeRef() must be able to create
		a reference to the receiver).
	
		Receivers are fairly flexible in their specification,
		as the machinery in the robustApply module takes care
		of most of the details regarding figuring out appropriate
		subsets of the sent arguments to apply to a given
		receiver.

		Note:
			if receiver is itself a weak reference (a callable),
			it will be de-referenced by the system's machinery,
			so *generally* weak references are not suitable as
			receivers, though some use might be found for the
			facility whereby a higher-level library passes in
			pre-weakrefed receiver references.

	signal -- the signal to which the receiver should respond
	
		if Any, receiver will receive any signal from the
		indicated sender (which might also be Any, but is not
		necessarily Any).
		
		Otherwise must be a hashable Python object other than
		None (DispatcherError raised on None).
		
	sender -- the sender to which the receiver should respond
	
		if Any, receiver will receive the indicated signals
		from any sender.
		
		if Anonymous, receiver will only receive indicated
		signals from send/sendExact which do not specify a
		sender, or specify Anonymous explicitly as the sender.

		Otherwise can be any python object.
		
	weak -- whether to use weak references to the receiver
		By default, the module will attempt to use weak
		references to the receiver objects.  If this parameter
		is false, then strong references will be used.

	returns None, may raise DispatcherTypeError
	"""
	if signal is None:
		raise errors.DispatcherTypeError(
			'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
		)
	if weak:
		receiver = saferef.safeRef(receiver, onDelete=_removeReceiver)
	senderkey = id(sender)
	if connections.has_key(senderkey):
		signals = connections[senderkey]
	else:
		connections[senderkey] = signals = {}
	# Keep track of senders for cleanup.
	# Is Anonymous something we want to clean up?
	if sender not in (None, Anonymous, Any):
		def remove(object, senderkey=senderkey):
			_removeSender(senderkey=senderkey)
		# Skip objects that can not be weakly referenced, which means
		# they won't be automatically cleaned up, but that's too bad.
		try:
			weakSender = weakref.ref(sender, remove)
			senders[senderkey] = weakSender
		except:
			pass
		
	receiverID = id(receiver)
	# get current set, remove any current references to
	# this receiver in the set, including back-references
	if signals.has_key(signal):
		receivers = signals[signal]
		_removeOldBackRefs(senderkey, signal, receiver, receivers)
	else:
		receivers = signals[signal] = []
	try:
		current = sendersBack.get( receiverID )
		if current is None:
			sendersBack[ receiverID ] = current = []
		if senderkey not in current:
			current.append(senderkey)
	except:
		pass

	receivers.append(receiver)



def disconnect(receiver, signal=Any, sender=Any, weak=True):
	"""Disconnect receiver from sender for signal

	receiver -- the registered receiver to disconnect
	signal -- the registered signal to disconnect
	sender -- the registered sender to disconnect
	weak -- the weakref state to disconnect

	disconnect reverses the process of connect,
	the semantics for the individual elements are
	logically equivalent to a tuple of
	(receiver, signal, sender, weak) used as a key
	to be deleted from the internal routing tables.
	(The actual process is slightly more complex
	but the semantics are basically the same).

	Note:
		Using disconnect is not required to cleanup
		routing when an object is deleted, the framework
		will remove routes for deleted objects
		automatically.  It's only necessary to disconnect
		if you want to stop routing to a live object.
		
	returns None, may raise DispatcherTypeError or
		DispatcherKeyError
	"""
	if signal is None:
		raise errors.DispatcherTypeError(
			'Signal cannot be None (receiver=%r sender=%r)'%( receiver,sender)
		)
	if weak: receiver = saferef.safeRef(receiver)
	senderkey = id(sender)
	try:
		signals = connections[senderkey]
		receivers = signals[signal]
	except KeyError:
		raise errors.DispatcherKeyError(
			"""No receivers found for signal %r from sender %r""" %(
				signal,
				sender
			)
		)
	try:
		# also removes from receivers
		_removeOldBackRefs(senderkey, signal, receiver, receivers)
	except ValueError:
		raise errors.DispatcherKeyError(
			"""No connection to receiver %s for signal %s from sender %s""" %(
				receiver,
				signal,
				sender
			)
		)
	_cleanupConnections(senderkey, signal)

def getReceivers( sender = Any, signal = Any ):
	"""Get list of receivers from global tables

	This utility function allows you to retrieve the
	raw list of receivers from the connections table
	for the given sender and signal pair.

	Note:
		there is no guarantee that this is the actual list
		stored in the connections table, so the value
		should be treated as a simple iterable/truth value
		rather than, for instance a list to which you
		might append new records.

	Normally you would use liveReceivers( getReceivers( ...))
	to retrieve the actual receiver objects as an iterable
	object.
	"""
	try:
		return connections[id(sender)][signal]
	except KeyError:
		return []

def liveReceivers(receivers):
	"""Filter sequence of receivers to get resolved, live receivers

	This is a generator which will iterate over
	the passed sequence, checking for weak references
	and resolving them, then returning all live
	receivers.
	"""
	for receiver in receivers:
		if isinstance( receiver, WEAKREF_TYPES):
			# Dereference the weak reference.
			receiver = receiver()
			if receiver is not None:
				yield receiver
		else:
			yield receiver



def getAllReceivers( sender = Any, signal = Any ):
	"""Get list of all receivers from global tables

	This gets all receivers which should receive
	the given signal from sender, each receiver should
	be produced only once by the resulting generator
	"""
	receivers = {}
	for set in (
		# Get receivers that receive *this* signal from *this* sender.
		getReceivers( sender, signal ),
		# Add receivers that receive *any* signal from *this* sender.
		getReceivers( sender, Any ),
		# Add receivers that receive *this* signal from *any* sender.
		getReceivers( Any, signal ),
		# Add receivers that receive *any* signal from *any* sender.
		getReceivers( Any, Any ),
	):
		for receiver in set:
			if receiver: # filter out dead instance-method weakrefs
				try:
					if not receivers.has_key( receiver ):
						receivers[receiver] = 1
						yield receiver
				except TypeError:
					# dead weakrefs raise TypeError on hash...
					pass

def send(signal=Any, sender=Anonymous, *arguments, **named):
	"""Send signal from sender to all connected receivers.
	
	signal -- (hashable) signal value, see connect for details

	sender -- the sender of the signal
	
		if Any, only receivers registered for Any will receive
		the message.

		if Anonymous, only receivers registered to receive
		messages from Anonymous or Any will receive the message

		Otherwise can be any python object (normally one
		registered with a connect if you actually want
		something to occur).

	arguments -- positional arguments which will be passed to
		*all* receivers. Note that this may raise TypeErrors
		if the receivers do not allow the particular arguments.
		Note also that arguments are applied before named
		arguments, so they should be used with care.

	named -- named arguments which will be filtered according
		to the parameters of the receivers to only provide those
		acceptable to the receiver.

	Return a list of tuple pairs [(receiver, response), ... ]

	if any receiver raises an error, the error propagates back
	through send, terminating the dispatch loop, so it is quite
	possible to not have all receivers called if a raises an
	error.
	"""
	# Call each receiver with whatever arguments it can accept.
	# Return a list of tuple pairs [(receiver, response), ... ].
	responses = []
	for receiver in liveReceivers(getAllReceivers(sender, signal)):
		response = robustapply.robustApply(
			receiver,
			signal=signal,
			sender=sender,
			*arguments,
			**named
		)
		responses.append((receiver, response))
	return responses
def sendExact( signal=Any, sender=Anonymous, *arguments, **named ):
	"""Send signal only to those receivers registered for exact message

	sendExact allows for avoiding Any/Anonymous registered
	handlers, sending only to those receivers explicitly
	registered for a particular signal on a particular
	sender.
	"""
	responses = []
	for receiver in liveReceivers(getReceivers(sender, signal)):
		response = robustapply.robustApply(
			receiver,
			signal=signal,
			sender=sender,
			*arguments,
			**named
		)
		responses.append((receiver, response))
	return responses
	

def _removeReceiver(receiver):
	"""Remove receiver from connections."""
	if not sendersBack:
		# During module cleanup the mapping will be replaced with None
		return False
	backKey = id(receiver)
	for senderkey in sendersBack.get(backKey,()):
		try:
			signals = connections[senderkey].keys()
		except KeyError,err:
			pass
		else:
			for signal in signals:
				try:
					receivers = connections[senderkey][signal]
				except KeyError:
					pass
				else:
					try:
						receivers.remove( receiver )
					except Exception, err:
						pass
				_cleanupConnections(senderkey, signal)
	try:
		del sendersBack[ backKey ]
	except KeyError:
		pass
			
def _cleanupConnections(senderkey, signal):
	"""Delete any empty signals for senderkey. Delete senderkey if empty."""
	try:
		receivers = connections[senderkey][signal]
	except:
		pass
	else:
		if not receivers:
			# No more connected receivers. Therefore, remove the signal.
			try:
				signals = connections[senderkey]
			except KeyError:
				pass
			else:
				del signals[signal]
				if not signals:
					# No more signal connections. Therefore, remove the sender.
					_removeSender(senderkey)

def _removeSender(senderkey):
	"""Remove senderkey from connections."""
	_removeBackrefs(senderkey)
	try:
		del connections[senderkey]
	except KeyError:
		pass
	# Senderkey will only be in senders dictionary if sender 
	# could be weakly referenced.
	try: 
		del senders[senderkey]
	except: 
		pass


def _removeBackrefs( senderkey):
	"""Remove all back-references to this senderkey"""
	try:
		signals = connections[senderkey]
	except KeyError:
		signals = None
	else:
		items = signals.items()
		def allReceivers( ):
			for signal,set in items:
				for item in set:
					yield item
		for receiver in allReceivers():
			_killBackref( receiver, senderkey )

def _removeOldBackRefs(senderkey, signal, receiver, receivers):
	"""Kill old sendersBack references from receiver

	This guards against multiple registration of the same
	receiver for a given signal and sender leaking memory
	as old back reference records build up.

	Also removes old receiver instance from receivers
	"""
	try:
		index = receivers.index(receiver)
		# need to scan back references here and remove senderkey
	except ValueError:
		return False
	else:
		oldReceiver = receivers[index]
		del receivers[index]
		found = 0
		signals = connections.get(signal)
		if signals is not None:
			for sig,recs in connections.get(signal,{}).iteritems():
				if sig != signal:
					for rec in recs:
						if rec is oldReceiver:
							found = 1
							break
		if not found:
			_killBackref( oldReceiver, senderkey )
			return True
		return False
		
		
def _killBackref( receiver, senderkey ):
	"""Do the actual removal of back reference from receiver to senderkey"""
	receiverkey = id(receiver)
	set = sendersBack.get( receiverkey, () )
	while senderkey in set:
		try:
			set.remove( senderkey )
		except:
			break
	if not set:
		try:
			del sendersBack[ receiverkey ]
		except KeyError:
			pass
	return True