Skip to content

Commit 9a6330f

Browse files
committed
Merge branch 'master' into convar_changed
2 parents 3f07345 + 39ca701 commit 9a6330f

File tree

15 files changed

+169
-94
lines changed

15 files changed

+169
-94
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/players/_base.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -405,22 +405,6 @@ def set_eye_location(self, eye_location):
405405

406406
eye_location = property(Entity.get_eye_location, set_eye_location)
407407

408-
def get_view_angle(self):
409-
"""Return the player's view angle.
410-
411-
:rtype: QAngle
412-
"""
413-
return super().view_angle
414-
415-
def set_view_angle(self, angle):
416-
"""Set the player's view angle."""
417-
# Make sure that only QAngle objects are passed. Otherwise you can
418-
# easily crash the server or cause unexpected behaviour
419-
assert isinstance(angle, QAngle)
420-
self.teleport(None, angle, None)
421-
422-
view_angle = property(get_view_angle, set_view_angle)
423-
424408
def push(self, horiz_mul, vert_mul, vert_override=False):
425409
"""Push the player along his view vector.
426410

addons/source-python/packages/source-python/players/constants.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
# =============================================================================
1717
# Source.Python Imports
1818
# Players
19+
from _players._constants import FIXANGLE_NONE
20+
from _players._constants import FIXANGLE_ABSOLUTE
21+
from _players._constants import FIXANGLE_RELATIVE
1922
from _players._constants import FL_ONGROUND
2023
from _players._constants import FL_DUCKING
2124
from _players._constants import FL_WATERJUMP
@@ -93,7 +96,8 @@
9396
# =============================================================================
9497
# >> ALL DECLARATION
9598
# =============================================================================
96-
__all__ = ('HideHudFlags',
99+
__all__ = ('FixAngle',
100+
'HideHudFlags',
97101
'HitGroup',
98102
'INVALID_PLAYER_USERID',
99103
'LifeState',
@@ -107,6 +111,14 @@
107111
# =============================================================================
108112
# >> ENUMERATORS
109113
# =============================================================================
114+
class FixAngle(IntEnum):
115+
"""Player fix angle enumerator."""
116+
117+
NONE = FIXANGLE_NONE
118+
ABSOLUTE = FIXANGLE_ABSOLUTE
119+
RELATIVE = FIXANGLE_RELATIVE
120+
121+
110122
class PlayerStates(IntFlag):
111123
"""Player states wrapper enumerator."""
112124

0 commit comments

Comments
 (0)