Skip to content

Commit 0146523

Browse files
authored
Merge branch 'Source-Python-Dev-Team:master' into master
2 parents 163b2a2 + 1f87696 commit 0146523

File tree

8 files changed

+105
-68
lines changed

8 files changed

+105
-68
lines changed

addons/source-python/packages/source-python/__init__.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ def new_open(f, *args, **kwargs):
6868
# =============================================================================
6969
# >> IMPORTS
7070
# =============================================================================
71-
# Python Imports
72-
# Context
73-
from contextlib import suppress
74-
7571
# Source.Python Imports
7672
# Loggers
7773
from loggers import _sp_logger # It's save to import this here
@@ -428,9 +424,11 @@ def remove_entities_listener():
428424
from _core import _sp_plugin
429425
from memory.manager import manager
430426

431-
with suppress(NameError):
427+
try:
432428
manager.get_global_pointer('GlobalEntityList').remove_entity_listener(
433429
_sp_plugin)
430+
except NameError:
431+
pass
434432

435433

436434
# =============================================================================

addons/source-python/packages/source-python/commands/typed.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
# >> IMPORTS
88
# =============================================================================
99
# Python Imports
10-
# Contextlib
11-
from contextlib import suppress
1210
# Inspect
1311
import inspect
1412
from inspect import Parameter
@@ -577,10 +575,12 @@ def __call__(self, callback):
577575
return callback
578576

579577
def _unload_instance(self):
580-
with suppress(ValueError):
578+
try:
581579
if self.parser.remove_command(self.commands):
582580
self.manager.unregister_commands(
583581
self.command.command_to_register, self.on_command)
582+
except ValueError:
583+
pass
584584

585585
@classmethod
586586
def on_command(cls, command, *args):

addons/source-python/packages/source-python/engines/precache.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
# =============================================================================
66
# >> IMPORTS
77
# =============================================================================
8-
# Python Imports
9-
# Contextlib
10-
from contextlib import suppress
11-
128
# Source.Python Imports
139
# Core
1410
from core import AutoUnload
@@ -119,8 +115,10 @@ def _server_spawn(self, game_event):
119115
def _unload_instance(self):
120116
"""Remove from the downloads list and unregister server_spawn."""
121117
# Remove the path from the downloads list
122-
with suppress(AttributeError):
118+
try:
123119
self._downloads._unload_instance()
120+
except AttributeError:
121+
pass
124122

125123
# Unregister the server_spawn event
126124
event_manager.unregister_for_event('server_spawn', self._server_spawn)

addons/source-python/packages/source-python/entities/_base.py

Lines changed: 81 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
# Python Imports
99
# Collections
1010
from collections import defaultdict
11-
# Contextlib
12-
from contextlib import suppress
1311
# Inspect
1412
from inspect import signature
1513
# WeakRef
@@ -41,6 +39,7 @@
4139
from entities.classes import server_classes
4240
from entities.constants import WORLD_ENTITY_INDEX
4341
from entities.constants import DamageTypes
42+
from entities.datamaps import InputFunction
4443
from entities.helpers import index_from_inthandle
4544
from entities.helpers import index_from_pointer
4645
from entities.helpers import wrap_entity_mem_func
@@ -144,6 +143,17 @@ def __call__(cls, index, caching=None):
144143
# We are done, let's return the instance
145144
return obj
146145

146+
@cached_property(unbound=True)
147+
def attributes(cls):
148+
"""Returns all the attributes available for this class.
149+
150+
:rtype: dict
151+
"""
152+
attributes = {}
153+
for cls in reversed(cls.mro()):
154+
attributes.update(vars(cls))
155+
return attributes
156+
147157
@property
148158
def caching(cls):
149159
"""Returns whether this class is caching its instances by default.
@@ -208,54 +218,57 @@ def __hash__(self):
208218

209219
def __getattr__(self, attr):
210220
"""Find if the attribute is valid and returns the appropriate value."""
211-
# Loop through all of the entity's server classes
212-
for instance in self.server_classes.values():
213-
214-
try:
215-
# Get the attribute's value
216-
value = getattr(instance, attr)
217-
except AttributeError:
218-
continue
221+
# Try to resolve the dynamic attribute
222+
try:
223+
instance, value = self.dynamic_attributes[attr]
224+
except KeyError:
225+
raise AttributeError('Attribute "{0}" not found'.format(attr))
219226

220-
# Is the value a dynamic function?
221-
if isinstance(value, MemberFunction):
227+
# Is the attribute a property descriptor?
228+
try:
229+
value = value.__get__(instance)
230+
except AttributeError:
231+
pass
222232

223-
# Cache the value
224-
with suppress(AttributeError):
225-
object.__setattr__(self, attr, value)
233+
# Is the value a dynamic function?
234+
if isinstance(value, (MemberFunction, InputFunction)):
226235

227-
# Return the attribute's value
228-
return value
236+
# Cache the value
237+
try:
238+
object.__setattr__(self, attr, value)
239+
except AttributeError:
240+
pass
229241

230-
# If the attribute is not found, raise an error
231-
raise AttributeError('Attribute "{0}" not found'.format(attr))
242+
return value
232243

233244
def __setattr__(self, attr, value):
234245
"""Find if the attribute is valid and sets its value."""
235246
# Is the given attribute a property?
236-
if (attr in super().__dir__() and isinstance(
237-
getattr(self.__class__, attr, None), property)):
238-
239-
# Set the property's value
240-
object.__setattr__(self, attr, value)
241-
242-
# No need to go further
243-
return
247+
try:
248+
setter = type(self).attributes[attr].__set__
244249

245-
# Loop through all of the entity's server classes
246-
for server_class, instance in self.server_classes.items():
250+
# KeyError:
251+
# The attribute does not exist.
252+
# AttributeError:
253+
# The attribute is not a descriptor.
254+
except (KeyError, AttributeError):
247255

248-
# Does the current server class contain the given attribute?
249-
if hasattr(server_class, attr):
256+
# Try to resolve a dynamic attribute
257+
try:
258+
self, setter = self.dynamic_attributes[attr]
259+
setter = setter.__set__
250260

251-
# Set the attribute's value
252-
setattr(instance, attr, value)
261+
# KeyError:
262+
# The attribute does not exist.
263+
# AttributeError:
264+
# The attribute is not a descriptor.
265+
except (KeyError, AttributeError):
253266

254-
# No need to go further
255-
return
267+
# Set the attribute to the given value
268+
return object.__setattr__(self, attr, value)
256269

257-
# If the attribute is not found, just set the attribute
258-
super().__setattr__(attr, value)
270+
# Set the attribute's value
271+
setter(self, value)
259272

260273
def __dir__(self):
261274
"""Return an alphabetized list of attributes for the instance."""
@@ -317,9 +330,21 @@ def server_classes(self):
317330
"""Yield all server classes for the entity."""
318331
return {
319332
server_class: make_object(server_class, self.pointer) for
320-
server_class in server_classes.get_entity_server_classes(self)
333+
server_class in reversed(
334+
server_classes.get_entity_server_classes(self)
335+
)
321336
}
322337

338+
@cached_property
339+
def dynamic_attributes(self):
340+
"""Returns the dynamic attributes for this entity."""
341+
attributes = {}
342+
for cls, instance in self.server_classes.items():
343+
attributes.update(
344+
{attr:(instance, getattr(cls, attr)) for attr in dir(cls)}
345+
)
346+
return attributes
347+
323348
@cached_property
324349
def properties(self):
325350
"""Iterate over all descriptors available for the entity."""
@@ -679,34 +704,44 @@ def take_damage(
679704
if attacker_index is not None:
680705

681706
# Try to get the Entity instance of the attacker
682-
with suppress(ValueError):
707+
try:
683708
attacker = Entity(attacker_index)
709+
except ValueError:
710+
pass
684711

685712
# Was a weapon given?
686713
if weapon_index is not None:
687714

688715
# Try to get the Weapon instance of the weapon
689-
with suppress(ValueError):
716+
try:
690717
weapon = Weapon(weapon_index)
718+
except ValueError:
719+
pass
691720

692721
# Is there a weapon but no attacker?
693722
if attacker is None and weapon is not None:
694723

695724
# Try to get the attacker based off of the weapon's owner
696-
with suppress(ValueError, OverflowError):
725+
try:
697726
attacker_index = index_from_inthandle(weapon.owner_handle)
698727
attacker = Entity(attacker_index)
728+
except (ValueError, OverflowError):
729+
pass
699730

700731
# Is there an attacker but no weapon?
701732
if attacker is not None and weapon is None:
702733

703734
# Try to use the attacker's active weapon
704-
with suppress(AttributeError):
735+
try:
705736
weapon = attacker.active_weapon
737+
except AttributeError:
738+
pass
706739

707740
# Try to set the hitgroup
708-
with suppress(AttributeError):
741+
try:
709742
self.hitgroup = hitgroup
743+
except AttributeError:
744+
pass
710745

711746
# Get a TakeDamageInfo instance
712747
take_damage_info = TakeDamageInfo()
@@ -795,8 +830,10 @@ def _on_networked_entity_deleted(index):
795830
for delay in _entity_delays.pop(index, ()):
796831

797832
# Cancel the delay...
798-
with suppress(ValueError):
833+
try:
799834
delay.cancel()
835+
except ValueError:
836+
pass
800837

801838
# Loop through all repeats...
802839
for repeat in _entity_repeats.pop(index, ()):

addons/source-python/packages/source-python/entities/dictionary.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@
55
# ============================================================================
66
# >> IMPORTS
77
# ============================================================================
8-
# Python Imports
9-
# ContextLib
10-
from contextlib import suppress
11-
128
# Source.Python Imports
139
# Core
1410
from core import AutoUnload
@@ -98,8 +94,10 @@ def __delitem__(self, index):
9894
The index of the entity instance being removed.
9995
"""
10096
# Remove the given index from the dictionary...
101-
with suppress(KeyError):
97+
try:
10298
super().__delitem__(index)
99+
except KeyError:
100+
pass
103101

104102
def from_inthandle(self, inthandle):
105103
"""Returns an entity instance from an inthandle.

addons/source-python/packages/source-python/listeners/tick.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import math
1111
import time
1212

13-
from contextlib import suppress
1413
from enum import IntEnum
1514
from threading import Thread
1615
from warnings import warn
@@ -198,8 +197,10 @@ def time_elapsed(self):
198197
return time.time() - self._start_time
199198

200199
def _unload_instance(self):
201-
with suppress(ValueError):
200+
try:
202201
self.cancel()
202+
except ValueError:
203+
pass
203204

204205

205206
# =============================================================================

addons/source-python/packages/source-python/settings/types.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
# =============================================================================
88
# Python
99
from collections import OrderedDict
10-
from contextlib import suppress
1110

1211
# Source.Python
1312
from cvars import ConVar
@@ -100,7 +99,7 @@ def get_setting(self, index):
10099
value = engine_server.get_client_convar_value(index, self.convar)
101100

102101
# Try to typecast the value, suppressing ValueErrors
103-
with suppress(ValueError):
102+
try:
104103

105104
# Typecast the given value
106105
value = self._typecast_value(value)
@@ -111,6 +110,9 @@ def get_setting(self, index):
111110
# If so, return the value
112111
return value
113112

113+
except ValueError:
114+
pass
115+
114116
# Get the client's uniqueid
115117
uniqueid = uniqueid_from_index(index)
116118

@@ -124,7 +126,7 @@ def get_setting(self, index):
124126
value = _player_settings_storage[uniqueid][self.convar]
125127

126128
# Try to typecast the value, suppressing ValueErrors
127-
with suppress(ValueError):
129+
try:
128130

129131
# Typecast the given value
130132
value = self._typecast_value(value)
@@ -135,6 +137,9 @@ def get_setting(self, index):
135137
# Return the value
136138
return value
137139

140+
except ValueError:
141+
pass
142+
138143
# Return the default value
139144
return self._get_default_value()
140145

addons/source-python/packages/source-python/weapons/restrictions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ def _on_weapon_bump(args):
389389
make_object(Player, args[0]), edict_from_pointer(args[1]).classname)
390390

391391

392-
if GAME_NAME in ('css', 'csgo'):
392+
if GAME_NAME in ('cstrike', 'csgo'):
393393
@EntityPreHook(EntityCondition.is_player, 'buy_internal')
394394
def _on_weapon_purchase(args):
395395
"""Return whether the player is allowed to purchase the weapon."""

0 commit comments

Comments
 (0)