diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml new file mode 100644 index 0000000000..1266bfddfb --- /dev/null +++ b/.github/workflows/mypy.yml @@ -0,0 +1,23 @@ +name: Run Mypy +on: [push, pull_request] + +jobs: + mypy: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ['3.8', '3.11'] + fail-fast: false + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install mypy==1.4.0 + - name: Run mypy on direct + run: python tests/run_mypy.py diff --git a/direct/src/directbase/DirectStart.py b/direct/src/directbase/DirectStart.py index ea51d43fc9..2983c0b821 100644 --- a/direct/src/directbase/DirectStart.py +++ b/direct/src/directbase/DirectStart.py @@ -15,7 +15,7 @@ to and may be replaced by the following code: base = ShowBase() """ -__all__ = [] +__all__ = () if __debug__: print('Using deprecated DirectStart interface.') diff --git a/direct/src/directbase/TestStart.py b/direct/src/directbase/TestStart.py index b3602c9127..bdbab206e5 100755 --- a/direct/src/directbase/TestStart.py +++ b/direct/src/directbase/TestStart.py @@ -6,7 +6,7 @@ from direct.showbase import ShowBase base = ShowBase.ShowBase() # Put an axis in the world: -base.loader.loadModel("models/misc/xyzAxis").reparentTo(render) +base.loader.loadModel("models/misc/xyzAxis").reparentTo(base.render) base.camera.setPosHpr(0, -10.0, 0, 0, 0, 0) base.camLens.setFov(52.0) diff --git a/direct/src/directbase/ThreeUpStart.py b/direct/src/directbase/ThreeUpStart.py index dbdf6eb88a..3ca50b34fe 100644 --- a/direct/src/directbase/ThreeUpStart.py +++ b/direct/src/directbase/ThreeUpStart.py @@ -8,7 +8,7 @@ from direct.showbase import ThreeUpShow base = ThreeUpShow.ThreeUpShow() # Put an axis in the world: -base.loader.loadModel("models/misc/xyzAxis").reparentTo(render) +base.loader.loadModel("models/misc/xyzAxis").reparentTo(base.render) base.camera.setPosHpr(0, -10.0, 0, 0, 0, 0) base.camLens.setFov(52.0) diff --git a/direct/src/directdevices/DirectJoybox.py b/direct/src/directdevices/DirectJoybox.py index 2f5026504b..45daf64ee1 100644 --- a/direct/src/directdevices/DirectJoybox.py +++ b/direct/src/directdevices/DirectJoybox.py @@ -41,8 +41,12 @@ class DirectJoybox(DirectObject): xyzMultiplier = 1.0 hprMultiplier = 1.0 - def __init__(self, device = 'CerealBox', nodePath = base.direct.camera, - headingNP = base.direct.camera): + def __init__(self, device = 'CerealBox', nodePath = None, headingNP = None): + from direct.showbase.ShowBaseGlobal import base + if nodePath is None: + nodePath = base.direct.camera + if headingNP is None: + headingNP = base.direct.camera # See if device manager has been initialized if base.direct.deviceManager is None: base.direct.deviceManager = DirectDeviceManager() diff --git a/direct/src/distributed/AsyncRequest.py b/direct/src/distributed/AsyncRequest.py index 105d83837d..113c2aa31a 100755 --- a/direct/src/distributed/AsyncRequest.py +++ b/direct/src/distributed/AsyncRequest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + #from otp.ai.AIBaseGlobal import * from direct.directnotify import DirectNotifyGlobal from direct.showbase.DirectObject import DirectObject @@ -39,7 +41,7 @@ class AsyncRequest(DirectObject): will be called again when the new self.neededObjects is complete. You may repeat this as necessary. """ - _asyncRequests = {} + _asyncRequests: dict[int, AsyncRequest] = {} notify = DirectNotifyGlobal.directNotify.newCategory('AsyncRequest') diff --git a/direct/src/distributed/CachedDOData.py b/direct/src/distributed/CachedDOData.py index 99a600c05b..63afd2d9b7 100755 --- a/direct/src/distributed/CachedDOData.py +++ b/direct/src/distributed/CachedDOData.py @@ -20,3 +20,10 @@ class CachedDOData: # override and destroy the cached data # cached data is typically created by the DistributedObject and destroyed here pass + + # These next two methods tell mypy to allow arbitrary attributes. + def __getattribute__(self, name: str): + return object.__getattribute__(self, name) + + def __setattr__(self, name: str, value) -> None: + object.__setattr__(self, name, value) diff --git a/direct/src/distributed/DistributedObjectAI.py b/direct/src/distributed/DistributedObjectAI.py index 94de96abd5..b67ee57d1e 100644 --- a/direct/src/distributed/DistributedObjectAI.py +++ b/direct/src/distributed/DistributedObjectAI.py @@ -299,7 +299,7 @@ class DistributedObjectAI(DistributedObjectBase): # setLocation destroys self._zoneData if we move away to # a different zone if self._zoneData is None: - from otp.ai.AIZoneData import AIZoneData + from otp.ai.AIZoneData import AIZoneData # type: ignore[import] self._zoneData = AIZoneData(self.air, self.parentId, self.zoneId) return self._zoneData @@ -489,7 +489,7 @@ class DistributedObjectAI(DistributedObjectBase): # simultaneously on different lists of avatars, although they # should have different names. - from otp.ai import Barrier + from otp.ai import Barrier # type: ignore[import] context = self.__nextBarrierContext # We assume the context number is passed as a uint16. self.__nextBarrierContext = (self.__nextBarrierContext + 1) & 0xffff diff --git a/direct/src/distributed/DistributedObjectUD.py b/direct/src/distributed/DistributedObjectUD.py index 6874185a86..341ce41616 100755 --- a/direct/src/distributed/DistributedObjectUD.py +++ b/direct/src/distributed/DistributedObjectUD.py @@ -424,7 +424,7 @@ class DistributedObjectUD(DistributedObjectBase): # simultaneously on different lists of avatars, although they # should have different names. - from otp.ai import Barrier + from otp.ai import Barrier # type: ignore[import] context = self.__nextBarrierContext # We assume the context number is passed as a uint16. self.__nextBarrierContext = (self.__nextBarrierContext + 1) & 0xffff diff --git a/direct/src/distributed/DoInterestManager.py b/direct/src/distributed/DoInterestManager.py index 251e0b91a1..5876a7ae91 100755 --- a/direct/src/distributed/DoInterestManager.py +++ b/direct/src/distributed/DoInterestManager.py @@ -7,6 +7,8 @@ zone, remove interest in that zone. p.s. A great deal of this code is just code moved from ClientRepository.py. """ +from __future__ import annotations + from panda3d.core import ConfigVariableBool from .MsgTypes import CLIENT_ADD_INTEREST, CLIENT_ADD_INTEREST_MULTIPLE, CLIENT_REMOVE_INTEREST from direct.showbase import DirectObject @@ -98,9 +100,9 @@ class DoInterestManager(DirectObject.DirectObject): _ContextIdSerialNum = 100 _ContextIdMask = 0x3FFFFFFF # avoid making Python create a long - _interests = {} + _interests: dict[int, InterestState] = {} if __debug__: - _debug_interestHistory = [] + _debug_interestHistory: list[tuple] = [] _debug_maxDescriptionLen = 40 _SerialGen = SerialNumGen() diff --git a/direct/src/distributed/GridParent.py b/direct/src/distributed/GridParent.py index 3a38ae5d3a..2212ae39e5 100755 --- a/direct/src/distributed/GridParent.py +++ b/direct/src/distributed/GridParent.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from panda3d.core import NodePath # @@ -13,8 +15,8 @@ from panda3d.core import NodePath class GridParent: # this lets GridParents share CellOrigins - GridZone2CellOrigin = {} - GridZone2count = {} + GridZone2CellOrigin: dict[tuple, NodePath] = {} + GridZone2count: dict[tuple, int] = {} @staticmethod def getCellOrigin(grid, zoneId): tup = (grid, zoneId) diff --git a/direct/src/distributed/MsgTypes.py b/direct/src/distributed/MsgTypes.py index e595d3d88a..3e0a204a0c 100644 --- a/direct/src/distributed/MsgTypes.py +++ b/direct/src/distributed/MsgTypes.py @@ -1,143 +1,145 @@ """MsgTypes module: contains distributed object message types""" +from __future__ import annotations + from direct.showbase.PythonUtil import invertDictLossless -MsgName2Id = { - 'CLIENT_HELLO': 1, - 'CLIENT_HELLO_RESP': 2, +CLIENT_HELLO = 1 +CLIENT_HELLO_RESP = 2 - # Sent by the client when it's leaving. - 'CLIENT_DISCONNECT': 3, +# Sent by the client when it's leaving. +CLIENT_DISCONNECT = 3 - # Sent by the server when it is dropping the connection deliberately. - 'CLIENT_EJECT': 4, +# Sent by the server when it is dropping the connection deliberately. +CLIENT_EJECT = 4 - 'CLIENT_HEARTBEAT': 5, +CLIENT_HEARTBEAT = 5 - 'CLIENT_OBJECT_SET_FIELD': 120, - 'CLIENT_OBJECT_SET_FIELDS': 121, - 'CLIENT_OBJECT_LEAVING': 132, - 'CLIENT_OBJECT_LEAVING_OWNER': 161, - 'CLIENT_ENTER_OBJECT_REQUIRED': 142, - 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER': 143, - 'CLIENT_ENTER_OBJECT_REQUIRED_OWNER': 172, - 'CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER': 173, +CLIENT_OBJECT_SET_FIELD = 120 +CLIENT_OBJECT_SET_FIELDS = 121 +CLIENT_OBJECT_LEAVING = 132 +CLIENT_OBJECT_LEAVING_OWNER = 161 +CLIENT_ENTER_OBJECT_REQUIRED = 142 +CLIENT_ENTER_OBJECT_REQUIRED_OTHER = 143 +CLIENT_ENTER_OBJECT_REQUIRED_OWNER = 172 +CLIENT_ENTER_OBJECT_REQUIRED_OTHER_OWNER = 173 - 'CLIENT_DONE_INTEREST_RESP': 204, +CLIENT_DONE_INTEREST_RESP = 204 - 'CLIENT_ADD_INTEREST': 200, - 'CLIENT_ADD_INTEREST_MULTIPLE': 201, - 'CLIENT_REMOVE_INTEREST': 203, - 'CLIENT_OBJECT_LOCATION': 140, +CLIENT_ADD_INTEREST = 200 +CLIENT_ADD_INTEREST_MULTIPLE = 201 +CLIENT_REMOVE_INTEREST = 203 +CLIENT_OBJECT_LOCATION = 140 - # These are sent internally inside the Astron cluster. +# These are sent internally inside the Astron cluster. - # Message Director control messages: - 'CONTROL_CHANNEL': 1, - 'CONTROL_ADD_CHANNEL': 9000, - 'CONTROL_REMOVE_CHANNEL': 9001, - 'CONTROL_ADD_RANGE': 9002, - 'CONTROL_REMOVE_RANGE': 9003, - 'CONTROL_ADD_POST_REMOVE': 9010, - 'CONTROL_CLEAR_POST_REMOVES': 9011, +# Message Director control messages: +CONTROL_CHANNEL = 1 +CONTROL_ADD_CHANNEL = 9000 +CONTROL_REMOVE_CHANNEL = 9001 +CONTROL_ADD_RANGE = 9002 +CONTROL_REMOVE_RANGE = 9003 +CONTROL_ADD_POST_REMOVE = 9010 +CONTROL_CLEAR_POST_REMOVES = 9011 - # State Server control messages: - 'STATESERVER_CREATE_OBJECT_WITH_REQUIRED': 2000, - 'STATESERVER_CREATE_OBJECT_WITH_REQUIRED_OTHER': 2001, - 'STATESERVER_DELETE_AI_OBJECTS': 2009, - 'STATESERVER_OBJECT_GET_FIELD': 2010, - 'STATESERVER_OBJECT_GET_FIELD_RESP': 2011, - 'STATESERVER_OBJECT_GET_FIELDS': 2012, - 'STATESERVER_OBJECT_GET_FIELDS_RESP': 2013, - 'STATESERVER_OBJECT_GET_ALL': 2014, - 'STATESERVER_OBJECT_GET_ALL_RESP': 2015, - 'STATESERVER_OBJECT_SET_FIELD': 2020, - 'STATESERVER_OBJECT_SET_FIELDS': 2021, - 'STATESERVER_OBJECT_DELETE_FIELD_RAM': 2030, - 'STATESERVER_OBJECT_DELETE_FIELDS_RAM': 2031, - 'STATESERVER_OBJECT_DELETE_RAM': 2032, - 'STATESERVER_OBJECT_SET_LOCATION': 2040, - 'STATESERVER_OBJECT_CHANGING_LOCATION': 2041, - 'STATESERVER_OBJECT_ENTER_LOCATION_WITH_REQUIRED': 2042, - 'STATESERVER_OBJECT_ENTER_LOCATION_WITH_REQUIRED_OTHER': 2043, - 'STATESERVER_OBJECT_GET_LOCATION': 2044, - 'STATESERVER_OBJECT_GET_LOCATION_RESP': 2045, - 'STATESERVER_OBJECT_SET_AI': 2050, - 'STATESERVER_OBJECT_CHANGING_AI': 2051, - 'STATESERVER_OBJECT_ENTER_AI_WITH_REQUIRED': 2052, - 'STATESERVER_OBJECT_ENTER_AI_WITH_REQUIRED_OTHER': 2053, - 'STATESERVER_OBJECT_GET_AI': 2054, - 'STATESERVER_OBJECT_GET_AI_RESP': 2055, - 'STATESERVER_OBJECT_SET_OWNER': 2060, - 'STATESERVER_OBJECT_CHANGING_OWNER': 2061, - 'STATESERVER_OBJECT_ENTER_OWNER_WITH_REQUIRED': 2062, - 'STATESERVER_OBJECT_ENTER_OWNER_WITH_REQUIRED_OTHER': 2063, - 'STATESERVER_OBJECT_GET_OWNER': 2064, - 'STATESERVER_OBJECT_GET_OWNER_RESP': 2065, - 'STATESERVER_OBJECT_GET_ZONE_OBJECTS': 2100, - 'STATESERVER_OBJECT_GET_ZONES_OBJECTS': 2102, - 'STATESERVER_OBJECT_GET_CHILDREN': 2104, - 'STATESERVER_OBJECT_GET_ZONE_COUNT': 2110, - 'STATESERVER_OBJECT_GET_ZONE_COUNT_RESP': 2111, - 'STATESERVER_OBJECT_GET_ZONES_COUNT': 2112, - 'STATESERVER_OBJECT_GET_ZONES_COUNT_RESP': 2113, - 'STATESERVER_OBJECT_GET_CHILD_COUNT': 2114, - 'STATESERVER_OBJECT_GET_CHILD_COUNT_RESP': 2115, - 'STATESERVER_OBJECT_DELETE_ZONE': 2120, - 'STATESERVER_OBJECT_DELETE_ZONES': 2122, - 'STATESERVER_OBJECT_DELETE_CHILDREN': 2124, - # DBSS-backed-object messages: - 'DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS': 2200, - 'DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS_OTHER': 2201, - 'DBSS_OBJECT_GET_ACTIVATED': 2207, - 'DBSS_OBJECT_GET_ACTIVATED_RESP': 2208, - 'DBSS_OBJECT_DELETE_FIELD_DISK': 2230, - 'DBSS_OBJECT_DELETE_FIELDS_DISK': 2231, - 'DBSS_OBJECT_DELETE_DISK': 2232, +# State Server control messages: +STATESERVER_CREATE_OBJECT_WITH_REQUIRED = 2000 +STATESERVER_CREATE_OBJECT_WITH_REQUIRED_OTHER = 2001 +STATESERVER_DELETE_AI_OBJECTS = 2009 +STATESERVER_OBJECT_GET_FIELD = 2010 +STATESERVER_OBJECT_GET_FIELD_RESP = 2011 +STATESERVER_OBJECT_GET_FIELDS = 2012 +STATESERVER_OBJECT_GET_FIELDS_RESP = 2013 +STATESERVER_OBJECT_GET_ALL = 2014 +STATESERVER_OBJECT_GET_ALL_RESP = 2015 +STATESERVER_OBJECT_SET_FIELD = 2020 +STATESERVER_OBJECT_SET_FIELDS = 2021 +STATESERVER_OBJECT_DELETE_FIELD_RAM = 2030 +STATESERVER_OBJECT_DELETE_FIELDS_RAM = 2031 +STATESERVER_OBJECT_DELETE_RAM = 2032 +STATESERVER_OBJECT_SET_LOCATION = 2040 +STATESERVER_OBJECT_CHANGING_LOCATION = 2041 +STATESERVER_OBJECT_ENTER_LOCATION_WITH_REQUIRED = 2042 +STATESERVER_OBJECT_ENTER_LOCATION_WITH_REQUIRED_OTHER = 2043 +STATESERVER_OBJECT_GET_LOCATION = 2044 +STATESERVER_OBJECT_GET_LOCATION_RESP = 2045 +STATESERVER_OBJECT_SET_AI = 2050 +STATESERVER_OBJECT_CHANGING_AI = 2051 +STATESERVER_OBJECT_ENTER_AI_WITH_REQUIRED = 2052 +STATESERVER_OBJECT_ENTER_AI_WITH_REQUIRED_OTHER = 2053 +STATESERVER_OBJECT_GET_AI = 2054 +STATESERVER_OBJECT_GET_AI_RESP = 2055 +STATESERVER_OBJECT_SET_OWNER = 2060 +STATESERVER_OBJECT_CHANGING_OWNER = 2061 +STATESERVER_OBJECT_ENTER_OWNER_WITH_REQUIRED = 2062 +STATESERVER_OBJECT_ENTER_OWNER_WITH_REQUIRED_OTHER = 2063 +STATESERVER_OBJECT_GET_OWNER = 2064 +STATESERVER_OBJECT_GET_OWNER_RESP = 2065 +STATESERVER_OBJECT_GET_ZONE_OBJECTS = 2100 +STATESERVER_OBJECT_GET_ZONES_OBJECTS = 2102 +STATESERVER_OBJECT_GET_CHILDREN = 2104 +STATESERVER_OBJECT_GET_ZONE_COUNT = 2110 +STATESERVER_OBJECT_GET_ZONE_COUNT_RESP = 2111 +STATESERVER_OBJECT_GET_ZONES_COUNT = 2112 +STATESERVER_OBJECT_GET_ZONES_COUNT_RESP = 2113 +STATESERVER_OBJECT_GET_CHILD_COUNT = 2114 +STATESERVER_OBJECT_GET_CHILD_COUNT_RESP = 2115 +STATESERVER_OBJECT_DELETE_ZONE = 2120 +STATESERVER_OBJECT_DELETE_ZONES = 2122 +STATESERVER_OBJECT_DELETE_CHILDREN = 2124 +# DBSS-backed-object messages: +DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS = 2200 +DBSS_OBJECT_ACTIVATE_WITH_DEFAULTS_OTHER = 2201 +DBSS_OBJECT_GET_ACTIVATED = 2207 +DBSS_OBJECT_GET_ACTIVATED_RESP = 2208 +DBSS_OBJECT_DELETE_FIELD_DISK = 2230 +DBSS_OBJECT_DELETE_FIELDS_DISK = 2231 +DBSS_OBJECT_DELETE_DISK = 2232 - # Database Server control messages: - 'DBSERVER_CREATE_OBJECT': 3000, - 'DBSERVER_CREATE_OBJECT_RESP': 3001, - 'DBSERVER_OBJECT_GET_FIELD': 3010, - 'DBSERVER_OBJECT_GET_FIELD_RESP': 3011, - 'DBSERVER_OBJECT_GET_FIELDS': 3012, - 'DBSERVER_OBJECT_GET_FIELDS_RESP': 3013, - 'DBSERVER_OBJECT_GET_ALL': 3014, - 'DBSERVER_OBJECT_GET_ALL_RESP': 3015, - 'DBSERVER_OBJECT_SET_FIELD': 3020, - 'DBSERVER_OBJECT_SET_FIELDS': 3021, - 'DBSERVER_OBJECT_SET_FIELD_IF_EQUALS': 3022, - 'DBSERVER_OBJECT_SET_FIELD_IF_EQUALS_RESP': 3023, - 'DBSERVER_OBJECT_SET_FIELDS_IF_EQUALS': 3024, - 'DBSERVER_OBJECT_SET_FIELDS_IF_EQUALS_RESP': 3025, - 'DBSERVER_OBJECT_SET_FIELD_IF_EMPTY': 3026, - 'DBSERVER_OBJECT_SET_FIELD_IF_EMPTY_RESP': 3027, - 'DBSERVER_OBJECT_DELETE_FIELD': 3030, - 'DBSERVER_OBJECT_DELETE_FIELDS': 3031, - 'DBSERVER_OBJECT_DELETE': 3032, +# Database Server control messages: +DBSERVER_CREATE_OBJECT = 3000 +DBSERVER_CREATE_OBJECT_RESP = 3001 +DBSERVER_OBJECT_GET_FIELD = 3010 +DBSERVER_OBJECT_GET_FIELD_RESP = 3011 +DBSERVER_OBJECT_GET_FIELDS = 3012 +DBSERVER_OBJECT_GET_FIELDS_RESP = 3013 +DBSERVER_OBJECT_GET_ALL = 3014 +DBSERVER_OBJECT_GET_ALL_RESP = 3015 +DBSERVER_OBJECT_SET_FIELD = 3020 +DBSERVER_OBJECT_SET_FIELDS = 3021 +DBSERVER_OBJECT_SET_FIELD_IF_EQUALS = 3022 +DBSERVER_OBJECT_SET_FIELD_IF_EQUALS_RESP = 3023 +DBSERVER_OBJECT_SET_FIELDS_IF_EQUALS = 3024 +DBSERVER_OBJECT_SET_FIELDS_IF_EQUALS_RESP = 3025 +DBSERVER_OBJECT_SET_FIELD_IF_EMPTY = 3026 +DBSERVER_OBJECT_SET_FIELD_IF_EMPTY_RESP = 3027 +DBSERVER_OBJECT_DELETE_FIELD = 3030 +DBSERVER_OBJECT_DELETE_FIELDS = 3031 +DBSERVER_OBJECT_DELETE = 3032 - # Client Agent control messages: - 'CLIENTAGENT_SET_STATE': 1000, - 'CLIENTAGENT_SET_CLIENT_ID': 1001, - 'CLIENTAGENT_SEND_DATAGRAM': 1002, - 'CLIENTAGENT_EJECT': 1004, - 'CLIENTAGENT_DROP': 1005, - 'CLIENTAGENT_GET_NETWORK_ADDRESS': 1006, - 'CLIENTAGENT_GET_NETWORK_ADDRESS_RESP': 1007, - 'CLIENTAGENT_DECLARE_OBJECT': 1010, - 'CLIENTAGENT_UNDECLARE_OBJECT': 1011, - 'CLIENTAGENT_ADD_SESSION_OBJECT': 1012, - 'CLIENTAGENT_REMOVE_SESSION_OBJECT': 1013, - 'CLIENTAGENT_SET_FIELDS_SENDABLE': 1014, - 'CLIENTAGENT_OPEN_CHANNEL': 1100, - 'CLIENTAGENT_CLOSE_CHANNEL': 1101, - 'CLIENTAGENT_ADD_POST_REMOVE': 1110, - 'CLIENTAGENT_CLEAR_POST_REMOVES': 1111, - 'CLIENTAGENT_ADD_INTEREST': 1200, - 'CLIENTAGENT_ADD_INTEREST_MULTIPLE': 1201, - 'CLIENTAGENT_REMOVE_INTEREST': 1203, -} +# Client Agent control messages: +CLIENTAGENT_SET_STATE = 1000 +CLIENTAGENT_SET_CLIENT_ID = 1001 +CLIENTAGENT_SEND_DATAGRAM = 1002 +CLIENTAGENT_EJECT = 1004 +CLIENTAGENT_DROP = 1005 +CLIENTAGENT_GET_NETWORK_ADDRESS = 1006 +CLIENTAGENT_GET_NETWORK_ADDRESS_RESP = 1007 +CLIENTAGENT_DECLARE_OBJECT = 1010 +CLIENTAGENT_UNDECLARE_OBJECT = 1011 +CLIENTAGENT_ADD_SESSION_OBJECT = 1012 +CLIENTAGENT_REMOVE_SESSION_OBJECT = 1013 +CLIENTAGENT_SET_FIELDS_SENDABLE = 1014 +CLIENTAGENT_OPEN_CHANNEL = 1100 +CLIENTAGENT_CLOSE_CHANNEL = 1101 +CLIENTAGENT_ADD_POST_REMOVE = 1110 +CLIENTAGENT_CLEAR_POST_REMOVES = 1111 +CLIENTAGENT_ADD_INTEREST = 1200 +CLIENTAGENT_ADD_INTEREST_MULTIPLE = 1201 +CLIENTAGENT_REMOVE_INTEREST = 1203 + +MsgName2Id = {name: value for name, value in globals().items() if isinstance(value, int)} # create id->name table for debugging MsgId2Names = invertDictLossless(MsgName2Id) @@ -146,7 +148,7 @@ MsgId2Names = invertDictLossless(MsgName2Id) globals().update(MsgName2Id) # These messages are ignored when the client is headed to the quiet zone -QUIET_ZONE_IGNORED_LIST = [ +QUIET_ZONE_IGNORED_LIST: list[int] = [ # We mustn't ignore updates, because some updates for localToon # are always important. diff --git a/direct/src/distributed/MsgTypesCMU.py b/direct/src/distributed/MsgTypesCMU.py index ce728b3b6f..a348e01b3c 100644 --- a/direct/src/distributed/MsgTypesCMU.py +++ b/direct/src/distributed/MsgTypesCMU.py @@ -5,25 +5,22 @@ implementation. """ from direct.showbase.PythonUtil import invertDictLossless -MsgName2Id = { - 'SET_DOID_RANGE_CMU' : 9001, - 'CLIENT_OBJECT_GENERATE_CMU' : 9002, - 'OBJECT_GENERATE_CMU' : 9003, - 'OBJECT_UPDATE_FIELD_CMU' : 9004, - 'OBJECT_DISABLE_CMU' : 9005, - 'OBJECT_DELETE_CMU' : 9006, - 'REQUEST_GENERATES_CMU' : 9007, - 'CLIENT_DISCONNECT_CMU' : 9008, - 'CLIENT_SET_INTEREST_CMU' : 9009, - 'OBJECT_SET_ZONE_CMU' : 9010, - 'CLIENT_HEARTBEAT_CMU' : 9011, - 'CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU' : 9011, +SET_DOID_RANGE_CMU = 9001 +CLIENT_OBJECT_GENERATE_CMU = 9002 +OBJECT_GENERATE_CMU = 9003 +OBJECT_UPDATE_FIELD_CMU = 9004 +OBJECT_DISABLE_CMU = 9005 +OBJECT_DELETE_CMU = 9006 +REQUEST_GENERATES_CMU = 9007 +CLIENT_DISCONNECT_CMU = 9008 +CLIENT_SET_INTEREST_CMU = 9009 +OBJECT_SET_ZONE_CMU = 9010 +CLIENT_HEARTBEAT_CMU = 9011 +CLIENT_OBJECT_UPDATE_FIELD_TARGETED_CMU = 9011 - 'CLIENT_OBJECT_UPDATE_FIELD' : 120, # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD -} +CLIENT_OBJECT_UPDATE_FIELD = 120 # Matches MsgTypes.CLIENT_OBJECT_SET_FIELD + +MsgName2Id = {name: value for name, value in globals().items() if isinstance(value, int)} # create id->name table for debugging MsgId2Names = invertDictLossless(MsgName2Id) - -# put msg names in module scope, assigned to msg value -globals().update(MsgName2Id) diff --git a/direct/src/fsm/ClassicFSM.py b/direct/src/fsm/ClassicFSM.py index 6d45b5bb11..1b1be81d1d 100644 --- a/direct/src/fsm/ClassicFSM.py +++ b/direct/src/fsm/ClassicFSM.py @@ -5,6 +5,8 @@ Note: existing code. New code should use the :mod:`.FSM` module instead. """ +from __future__ import annotations + __all__ = ['ClassicFSM'] from direct.directnotify.DirectNotifyGlobal import directNotify @@ -13,7 +15,7 @@ from direct.showbase.MessengerGlobal import messenger import weakref if __debug__: - _debugFsms = {} + _debugFsms: dict[str, weakref.ref] = {} def printDebugFsmList(): for k in sorted(_debugFsms.keys()): diff --git a/direct/src/fsm/State.py b/direct/src/fsm/State.py index f80507a538..0b90ba16c7 100644 --- a/direct/src/fsm/State.py +++ b/direct/src/fsm/State.py @@ -1,5 +1,7 @@ """State module: contains State class""" +from __future__ import annotations + __all__ = ['State'] from direct.directnotify.DirectNotifyGlobal import directNotify @@ -18,7 +20,7 @@ class State(DirectObject): # should not cause any leaks. if __debug__: import weakref - States = weakref.WeakKeyDictionary() + States: weakref.WeakKeyDictionary[State, int] = weakref.WeakKeyDictionary() @classmethod def replaceMethod(cls, oldFunction, newFunction): diff --git a/direct/src/fsm/StatePush.py b/direct/src/fsm/StatePush.py index 21bed7e299..4e105e0b80 100755 --- a/direct/src/fsm/StatePush.py +++ b/direct/src/fsm/StatePush.py @@ -1,6 +1,8 @@ # classes for event-driven programming # http://en.wikipedia.org/wiki/Event-driven_programming +from __future__ import annotations + __all__ = ['StateVar', 'FunctionCall', 'EnterExit', 'Pulse', 'EventPulse', 'EventArgument', ] diff --git a/direct/src/gui/DirectDialog.py b/direct/src/gui/DirectDialog.py index 4b95dcb7f5..062b0c320c 100644 --- a/direct/src/gui/DirectDialog.py +++ b/direct/src/gui/DirectDialog.py @@ -4,6 +4,8 @@ See the :ref:`directdialog` page in the programming manual for a more in-depth explanation and an example of how to use this class. """ +from __future__ import annotations + __all__ = [ 'findDialog', 'cleanupDialog', 'DirectDialog', 'OkDialog', 'OkCancelDialog', 'YesNoDialog', 'YesNoCancelDialog', 'RetryCancelDialog', @@ -45,7 +47,7 @@ def cleanupDialog(uniqueName): class DirectDialog(DirectFrame): - AllDialogs = {} + AllDialogs: dict[str, DirectDialog] = {} PanelIndex = 0 def __init__(self, parent=None, **kw): diff --git a/direct/src/gui/DirectGuiBase.py b/direct/src/gui/DirectGuiBase.py index 24424855d0..f9bbb5b5f8 100644 --- a/direct/src/gui/DirectGuiBase.py +++ b/direct/src/gui/DirectGuiBase.py @@ -84,6 +84,8 @@ Code overview: see if any keywords are left unused. If so, an error is raised. """ +from __future__ import annotations + __all__ = ['DirectGuiBase', 'DirectGuiWidget'] @@ -680,7 +682,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath): else: inactiveInitState = DGG.DISABLED - guiDict = {} + guiDict: dict[str, DirectGuiWidget] = {} def __init__(self, parent = None, **kw): # Direct gui widgets are node paths diff --git a/direct/src/gui/DirectGuiGlobals.py b/direct/src/gui/DirectGuiGlobals.py index 66d14d092c..d41199af0e 100644 --- a/direct/src/gui/DirectGuiGlobals.py +++ b/direct/src/gui/DirectGuiGlobals.py @@ -3,7 +3,7 @@ Global definitions used by Direct Gui Classes and handy constants that can be used during widget construction """ -__all__ = [] +__all__ = () from panda3d.core import ( KeyboardButton, diff --git a/direct/src/interval/FunctionInterval.py b/direct/src/interval/FunctionInterval.py index c12be80189..60c0ab7edf 100644 --- a/direct/src/interval/FunctionInterval.py +++ b/direct/src/interval/FunctionInterval.py @@ -1,5 +1,7 @@ """FunctionInterval module: contains the FunctionInterval class""" +from __future__ import annotations + __all__ = ['FunctionInterval', 'EventInterval', 'AcceptInterval', 'IgnoreInterval', 'ParentInterval', 'WrtParentInterval', 'PosInterval', 'HprInterval', 'ScaleInterval', 'PosHprInterval', 'HprScaleInterval', 'PosHprScaleInterval', 'Func', 'Wait'] from panda3d.direct import WaitInterval @@ -23,7 +25,7 @@ class FunctionInterval(Interval.Interval): # should not cause any leaks. if __debug__: import weakref - FunctionIntervals = weakref.WeakKeyDictionary() + FunctionIntervals: weakref.WeakKeyDictionary[FunctionInterval, int] = weakref.WeakKeyDictionary() @classmethod def replaceMethod(cls, oldFunction, newFunction): diff --git a/direct/src/interval/IntervalTest.py b/direct/src/interval/IntervalTest.py index db533da5c4..8705f70581 100644 --- a/direct/src/interval/IntervalTest.py +++ b/direct/src/interval/IntervalTest.py @@ -1,6 +1,6 @@ """Undocumented Module""" -__all__ = [] +__all__ = () if __name__ == "__main__": @@ -26,7 +26,7 @@ if __name__ == "__main__": base = ShowBase() boat = base.loader.loadModel('models/misc/smiley') - boat.reparentTo(render) + boat.reparentTo(base.render) donald = Actor() donald.loadModel("phase_6/models/char/donald-wheel-1000") @@ -34,7 +34,7 @@ if __name__ == "__main__": donald.reparentTo(boat) dock = base.loader.loadModel('models/misc/smiley') - dock.reparentTo(render) + dock.reparentTo(base.render) sound = base.loader.loadSfx('phase_6/audio/sfx/SZ_DD_waterlap.mp3') foghorn = base.loader.loadSfx('phase_6/audio/sfx/SZ_DD_foghorn.mp3') @@ -93,7 +93,7 @@ if __name__ == "__main__": foghornSound = SoundInterval(foghorn, name='foghorn') soundTrack2 = Track([(foghornStartTime, foghornSound)], 'soundtrack2') - mtrack = MultiTrack([boatTrack, dockTrack, soundTrack, soundTrack2, waterEventTrack, + mtrack = MultiTrack([boatTrack, dockTrack, soundTrack, soundTrack2, waterEventTrack, # type: ignore[name-defined] donaldSteerTrack]) # Print out MultiTrack parameters print(mtrack) @@ -175,11 +175,11 @@ if __name__ == "__main__": # Just to take time i2 = LerpPosInterval(base.camera, 2.0, Point3(0, 10, 5)) # This will be relative to end of camera move - i3 = FunctionInterval(printPreviousEnd) + i3 = FunctionInterval(printPreviousEnd) # type: ignore[assignment] # Just to take time i4 = LerpPosInterval(base.camera, 2.0, Point3(0, 0, 5)) # This will be relative to the start of the camera move - i5 = FunctionInterval(printPreviousStart) + i5 = FunctionInterval(printPreviousStart) # type: ignore[assignment] # This will be relative to track start i6 = FunctionInterval(printTrackStart) # This will print some arguments diff --git a/direct/src/leveleditor/LevelEditorStart.py b/direct/src/leveleditor/LevelEditorStart.py index 27a8da1c40..61c5a808b6 100644 --- a/direct/src/leveleditor/LevelEditorStart.py +++ b/direct/src/leveleditor/LevelEditorStart.py @@ -4,7 +4,7 @@ if __name__ == '__main__': from direct.showbase.ShowBase import ShowBase base = ShowBase() - base.le = LevelEditor.LevelEditor() + base.le = LevelEditor.LevelEditor() # type: ignore[attr-defined] # You should define LevelEditor instance as # base.le so it can be reached in global scope diff --git a/direct/src/leveleditor/testData.py b/direct/src/leveleditor/testData.py index 2dc05f01e6..a1dda82faa 100755 --- a/direct/src/leveleditor/testData.py +++ b/direct/src/leveleditor/testData.py @@ -1,4 +1,5 @@ from panda3d.core import Point3, VBase3 +from direct.showbase.ShowBaseGlobal import base if hasattr(base, 'le'): objectMgr = base.le.objectMgr @@ -6,7 +7,7 @@ if hasattr(base, 'le'): ui.sceneGraphUI.reset() else: - objectMgr = base.objectMgr + objectMgr = base.objectMgr # type: ignore[attr-defined] # temporary place holder for nodepath objects = {} diff --git a/direct/src/motiontrail/MotionTrail.py b/direct/src/motiontrail/MotionTrail.py index 49b429374a..75c055196b 100644 --- a/direct/src/motiontrail/MotionTrail.py +++ b/direct/src/motiontrail/MotionTrail.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from panda3d.core import ( BoundingVolume, ColorBlendAttrib, @@ -92,7 +94,7 @@ class MotionTrail(NodePath, DirectObject): notify = directNotify.newCategory("MotionTrail") task_added = False - motion_trail_list = [] + motion_trail_list: list[MotionTrail] = [] motion_trail_task_name = "motion_trail_task" global_enable = True diff --git a/direct/src/showbase/ContainerLeakDetector.py b/direct/src/showbase/ContainerLeakDetector.py index ef1949f33c..2e5ed34ce3 100755 --- a/direct/src/showbase/ContainerLeakDetector.py +++ b/direct/src/showbase/ContainerLeakDetector.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from direct.directnotify.DirectNotifyGlobal import directNotify import direct.showbase.DConfig as config from direct.showbase.PythonUtil import makeFlywheelGen, flywheel @@ -982,7 +984,7 @@ class ContainerLeakDetector(Job): """ notify = directNotify.newCategory("ContainerLeakDetector") # set of containers that should not be examined - PrivateIds = set() + PrivateIds: set[int] = set() def __init__(self, name, firstCheckDelay = None): Job.__init__(self, name) diff --git a/direct/src/showbase/ContainerReport.py b/direct/src/showbase/ContainerReport.py index 71468bfbf6..a43194ab65 100755 --- a/direct/src/showbase/ContainerReport.py +++ b/direct/src/showbase/ContainerReport.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from direct.directnotify.DirectNotifyGlobal import directNotify from direct.showbase.PythonUtil import Queue, invertDictLossless from direct.showbase.PythonUtil import safeRepr @@ -11,7 +13,7 @@ import io class ContainerReport(Job): notify = directNotify.newCategory("ContainerReport") # set of containers that should not be included in the report - PrivateIds = set() + PrivateIds: set[int] = set() def __init__(self, name, log=False, limit=None, threaded=False): Job.__init__(self, name) diff --git a/direct/src/showbase/DConfig.py b/direct/src/showbase/DConfig.py index a0331632e2..bd36ec631f 100644 --- a/direct/src/showbase/DConfig.py +++ b/direct/src/showbase/DConfig.py @@ -1,6 +1,6 @@ "This module contains a deprecated shim emulating the old DConfig API." -__all__ = [] +__all__ = () from panda3d.core import (ConfigFlags, ConfigVariableBool, ConfigVariableInt, ConfigVariableDouble, ConfigVariableString) diff --git a/direct/src/showbase/DistancePhasedNode.py b/direct/src/showbase/DistancePhasedNode.py index 0f0a426e99..fc4c5a471b 100755 --- a/direct/src/showbase/DistancePhasedNode.py +++ b/direct/src/showbase/DistancePhasedNode.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from direct.showbase.DirectObject import DirectObject from direct.directnotify.DirectNotifyGlobal import directNotify from panda3d.core import ( @@ -62,7 +64,7 @@ class DistancePhasedNode(PhasedObject, DirectObject, NodePath): notify = directNotify.newCategory("DistancePhasedObject") __InstanceSequence = 0 - __InstanceDeque = [] + __InstanceDeque: list[int] = [] @staticmethod def __allocateId(): diff --git a/direct/src/showbase/ExceptionVarDump.py b/direct/src/showbase/ExceptionVarDump.py index b2cc73f68a..aad5850e6f 100755 --- a/direct/src/showbase/ExceptionVarDump.py +++ b/direct/src/showbase/ExceptionVarDump.py @@ -69,7 +69,7 @@ oldExcepthook = None # from its main exception handler wantStackDumpLog = False wantStackDumpUpload = False -variableDumpReasons = [] +variableDumpReasons: list = [] dumpOnExceptionInit = False diff --git a/direct/src/showbase/ObjectReport.py b/direct/src/showbase/ObjectReport.py index 5362716e25..b0aec6286f 100755 --- a/direct/src/showbase/ObjectReport.py +++ b/direct/src/showbase/ObjectReport.py @@ -11,6 +11,8 @@ >>> o.diff(o2) """ +from __future__ import annotations + __all__ = ['ExclusiveObjectPool', 'ObjectReport'] from direct.directnotify.DirectNotifyGlobal import directNotify @@ -26,8 +28,8 @@ import builtins class ExclusiveObjectPool(DirectObject): # ObjectPool specialization that excludes particular objects # IDs of objects to globally exclude from reporting - _ExclObjs = [] - _ExclObjIds = {} + _ExclObjs: list[object] = [] + _ExclObjIds: dict[int, int] = {} _SyncMaster = Sync('ExclusiveObjectPool.ExcludedObjectList') _SerialNumGen = SerialNumGen() diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index 7ca1b36fe1..d9ffa2aa35 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -1,5 +1,7 @@ """Contains miscellaneous utility functions and classes.""" +from __future__ import annotations + __all__ = [ 'indent', 'doc', 'adjust', 'difference', 'intersection', 'union', @@ -39,6 +41,7 @@ import time import builtins import importlib import functools +from typing import Callable __report_indent = 3 @@ -699,9 +702,9 @@ if __debug__: return profileDecorator # intercept profile-related file operations to avoid disk access - movedOpenFuncs = [] - movedDumpFuncs = [] - movedLoadFuncs = [] + movedOpenFuncs: list[Callable] = [] + movedDumpFuncs: list[Callable] = [] + movedLoadFuncs: list[Callable] = [] profileFilenames = set() profileFilenameList = Stack() profileFilename2file = {} @@ -1899,7 +1902,7 @@ class SubframeCall: class PStatScope: - collectors = {} + collectors: dict = {} def __init__(self, level = None): self.levels = [] @@ -2618,52 +2621,52 @@ class PriorityCallbacks: callback() -builtins.Functor = Functor -builtins.Stack = Stack -builtins.Queue = Queue -builtins.SerialNumGen = SerialNumGen -builtins.SerialMaskedGen = SerialMaskedGen -builtins.ScratchPad = ScratchPad -builtins.uniqueName = uniqueName -builtins.serialNum = serialNum +builtins.Functor = Functor # type: ignore[attr-defined] +builtins.Stack = Stack # type: ignore[attr-defined] +builtins.Queue = Queue # type: ignore[attr-defined] +builtins.SerialNumGen = SerialNumGen # type: ignore[attr-defined] +builtins.SerialMaskedGen = SerialMaskedGen # type: ignore[attr-defined] +builtins.ScratchPad = ScratchPad # type: ignore[attr-defined] +builtins.uniqueName = uniqueName # type: ignore[attr-defined] +builtins.serialNum = serialNum # type: ignore[attr-defined] if __debug__: - builtins.profiled = profiled - builtins.exceptionLogged = exceptionLogged -builtins.itype = itype -builtins.appendStr = appendStr -builtins.bound = bound -builtins.clamp = clamp -builtins.lerp = lerp -builtins.makeList = makeList -builtins.makeTuple = makeTuple + builtins.profiled = profiled # type: ignore[attr-defined] + builtins.exceptionLogged = exceptionLogged # type: ignore[attr-defined] +builtins.itype = itype # type: ignore[attr-defined] +builtins.appendStr = appendStr # type: ignore[attr-defined] +builtins.bound = bound # type: ignore[attr-defined] +builtins.clamp = clamp # type: ignore[attr-defined] +builtins.lerp = lerp # type: ignore[attr-defined] +builtins.makeList = makeList # type: ignore[attr-defined] +builtins.makeTuple = makeTuple # type: ignore[attr-defined] if __debug__: - builtins.printStack = printStack - builtins.printReverseStack = printReverseStack - builtins.printVerboseStack = printVerboseStack -builtins.DelayedCall = DelayedCall -builtins.DelayedFunctor = DelayedFunctor -builtins.FrameDelayedCall = FrameDelayedCall -builtins.SubframeCall = SubframeCall -builtins.invertDict = invertDict -builtins.invertDictLossless = invertDictLossless -builtins.getBase = getBase -builtins.getRepository = getRepository -builtins.safeRepr = safeRepr -builtins.fastRepr = fastRepr -builtins.nullGen = nullGen -builtins.flywheel = flywheel -builtins.loopGen = loopGen + builtins.printStack = printStack # type: ignore[attr-defined] + builtins.printReverseStack = printReverseStack # type: ignore[attr-defined] + builtins.printVerboseStack = printVerboseStack # type: ignore[attr-defined] +builtins.DelayedCall = DelayedCall # type: ignore[attr-defined] +builtins.DelayedFunctor = DelayedFunctor # type: ignore[attr-defined] +builtins.FrameDelayedCall = FrameDelayedCall # type: ignore[attr-defined] +builtins.SubframeCall = SubframeCall # type: ignore[attr-defined] +builtins.invertDict = invertDict # type: ignore[attr-defined] +builtins.invertDictLossless = invertDictLossless # type: ignore[attr-defined] +builtins.getBase = getBase # type: ignore[attr-defined] +builtins.getRepository = getRepository # type: ignore[attr-defined] +builtins.safeRepr = safeRepr # type: ignore[attr-defined] +builtins.fastRepr = fastRepr # type: ignore[attr-defined] +builtins.nullGen = nullGen # type: ignore[attr-defined] +builtins.flywheel = flywheel # type: ignore[attr-defined] +builtins.loopGen = loopGen # type: ignore[attr-defined] if __debug__: - builtins.StackTrace = StackTrace -builtins.report = report -builtins.pstatcollect = pstatcollect -builtins.MiniLog = MiniLog -builtins.MiniLogSentry = MiniLogSentry -builtins.logBlock = logBlock -builtins.HierarchyException = HierarchyException -builtins.deeptype = deeptype -builtins.Default = Default -builtins.configIsToday = configIsToday -builtins.typeName = typeName -builtins.safeTypeName = safeTypeName -builtins.histogramDict = histogramDict + builtins.StackTrace = StackTrace # type: ignore[attr-defined] +builtins.report = report # type: ignore[attr-defined] +builtins.pstatcollect = pstatcollect # type: ignore[attr-defined] +builtins.MiniLog = MiniLog # type: ignore[attr-defined] +builtins.MiniLogSentry = MiniLogSentry # type: ignore[attr-defined] +builtins.logBlock = logBlock # type: ignore[attr-defined] +builtins.HierarchyException = HierarchyException # type: ignore[attr-defined] +builtins.deeptype = deeptype # type: ignore[attr-defined] +builtins.Default = Default # type: ignore[attr-defined] +builtins.configIsToday = configIsToday # type: ignore[attr-defined] +builtins.typeName = typeName # type: ignore[attr-defined] +builtins.safeTypeName = safeTypeName # type: ignore[attr-defined] +builtins.histogramDict = histogramDict # type: ignore[attr-defined] diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index cebe0ad639..1eb2c9aa00 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -120,7 +120,7 @@ from direct.extensions_native import NodePath_extensions # pylint: disable=unuse # This needs to be available early for DirectGUI imports import sys import builtins -builtins.config = DConfig +builtins.config = DConfig # type: ignore[attr-defined] from direct.directnotify.DirectNotifyGlobal import directNotify, giveNotify from .MessengerGlobal import messenger diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 8b40d703ef..b24fca18fc 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -11,7 +11,7 @@ Note that you cannot directly import :data:`~builtins.base` from this module since ShowBase may not have been created yet; instead, ShowBase dynamically adds itself to this module's scope when instantiated.""" -__all__ = [] +__all__ = () from .ShowBase import ShowBase, WindowControls # pylint: disable=unused-import from direct.directnotify.DirectNotifyGlobal import directNotify, giveNotify # pylint: disable=unused-import @@ -23,6 +23,8 @@ import warnings __dev__ = ConfigVariableBool('want-dev', __debug__).value +base: ShowBase + #: The global instance of the :ref:`virtual-file-system`, as obtained using #: :meth:`panda3d.core.VirtualFileSystem.getGlobalPtr()`. vfs = VirtualFileSystem.getGlobalPtr() @@ -81,7 +83,7 @@ def inspect(anObject): import builtins -builtins.inspect = inspect +builtins.inspect = inspect # type: ignore[attr-defined] # this also appears in AIBaseGlobal if (not __debug__) and __dev__: diff --git a/direct/src/showbase/VerboseImport.py b/direct/src/showbase/VerboseImport.py index 9c61783ea5..181ac73c5d 100644 --- a/direct/src/showbase/VerboseImport.py +++ b/direct/src/showbase/VerboseImport.py @@ -3,7 +3,7 @@ This module hooks into Python's import mechanism to print out all imports to the standard output as they happen. """ -__all__ = [] +__all__ = () import sys diff --git a/direct/src/stdpy/pickle.py b/direct/src/stdpy/pickle.py index 4e03089f84..a44c3dd202 100644 --- a/direct/src/stdpy/pickle.py +++ b/direct/src/stdpy/pickle.py @@ -45,7 +45,7 @@ BasePickler = pickle._Pickler BaseUnpickler = pickle._Unpickler -class Pickler(BasePickler): +class Pickler(BasePickler): # type: ignore[misc, valid-type] def __init__(self, *args, **kw): self.bamWriter = BamWriter() @@ -148,7 +148,7 @@ class Pickler(BasePickler): self.save_reduce(obj=obj, *rv) -class Unpickler(BaseUnpickler): +class Unpickler(BaseUnpickler): # type: ignore[misc, valid-type] def __init__(self, *args, **kw): self.bamReader = BamReader() diff --git a/direct/src/stdpy/threading.py b/direct/src/stdpy/threading.py index e4e7a1d24f..3b82b61466 100644 --- a/direct/src/stdpy/threading.py +++ b/direct/src/stdpy/threading.py @@ -83,8 +83,8 @@ class ThreadBase: # Copy these static methods from Panda's Thread object. These are # useful if you may be running in Panda's SIMPLE_THREADS compilation # mode. -ThreadBase.forceYield = core.Thread.forceYield -ThreadBase.considerYield = core.Thread.considerYield +ThreadBase.forceYield = core.Thread.forceYield # type: ignore[attr-defined] +ThreadBase.considerYield = core.Thread.considerYield # type: ignore[attr-defined] class Thread(ThreadBase): diff --git a/direct/src/stdpy/threading2.py b/direct/src/stdpy/threading2.py index 8bdde3a27c..09d0a8d083 100644 --- a/direct/src/stdpy/threading2.py +++ b/direct/src/stdpy/threading2.py @@ -65,7 +65,7 @@ if __debug__: else: # Disable this when using "python -O" - class _Verbose(object): + class _Verbose(object): # type: ignore[no-redef] def __init__(self, verbose=None): pass def _note(self, *args): diff --git a/direct/src/task/Task.py b/direct/src/task/Task.py index 470eb73cdf..12716a6707 100644 --- a/direct/src/task/Task.py +++ b/direct/src/task/Task.py @@ -24,7 +24,7 @@ if hasattr(sys, 'getandroidapilevel'): signal = None else: try: - import _signal as signal + import _signal as signal # type: ignore[import, no-redef] except ImportError: signal = None diff --git a/direct/src/tkwidgets/AppShell.py b/direct/src/tkwidgets/AppShell.py index b5913e958e..6d4de85267 100644 --- a/direct/src/tkwidgets/AppShell.py +++ b/direct/src/tkwidgets/AppShell.py @@ -21,11 +21,11 @@ import builtins # Create toplevel widget dictionary if not hasattr(builtins, "widgetDict"): - builtins.widgetDict = {} + builtins.widgetDict = {} # type: ignore[attr-defined] # Create toplevel variable dictionary if not hasattr(builtins, "variableDict"): - builtins.variableDict = {} + builtins.variableDict = {} # type: ignore[attr-defined] def resetWidgetDict(): diff --git a/direct/src/wxwidgets/ViewPort.py b/direct/src/wxwidgets/ViewPort.py index 4c89637fb9..5e94330c76 100755 --- a/direct/src/wxwidgets/ViewPort.py +++ b/direct/src/wxwidgets/ViewPort.py @@ -6,6 +6,8 @@ Modified by gjeon. Modified by Summer 2010 Carnegie Mellon University ETC PandaLE team: fixed a bug in Viewport.Close """ +from __future__ import annotations + __all__ = ["Viewport", "ViewportManager"] from panda3d.core import ( @@ -36,7 +38,7 @@ VPPERSPECTIVE = 13 class ViewportManager: """Manages the global viewport stuff.""" - viewports = [] + viewports: list[Viewport] = [] gsg = None @staticmethod @@ -58,7 +60,7 @@ class ViewportManager: v.Layout(*args, **kwargs) -class Viewport(WxPandaWindow, DirectObject): +class Viewport(WxPandaWindow, DirectObject): # type: ignore[misc, valid-type] """Class representing a 3D Viewport.""" CREATENEW = CREATENEW VPLEFT = VPLEFT diff --git a/direct/src/wxwidgets/WxPandaStart.py b/direct/src/wxwidgets/WxPandaStart.py index 60ec8e0566..a561f24301 100755 --- a/direct/src/wxwidgets/WxPandaStart.py +++ b/direct/src/wxwidgets/WxPandaStart.py @@ -1,2 +1,3 @@ +from direct.showbase.ShowBaseGlobal import base from .WxPandaShell import WxPandaShell -base.app = WxPandaShell() +base.app = WxPandaShell() # type: ignore[attr-defined] diff --git a/direct/src/wxwidgets/WxPandaWindow.py b/direct/src/wxwidgets/WxPandaWindow.py index 4c1025f1a7..7f81c484ec 100644 --- a/direct/src/wxwidgets/WxPandaWindow.py +++ b/direct/src/wxwidgets/WxPandaWindow.py @@ -81,7 +81,7 @@ class EmbeddedPandaWindow(wx.Window): if not hasattr(wxgl, 'GLCanvas'): OpenGLPandaWindow = None else: - class OpenGLPandaWindow(wxgl.GLCanvas): + class OpenGLPandaWindow(wxgl.GLCanvas): # type: ignore[no-redef] """ This class implements a Panda3D "window" that actually draws within the wx GLCanvas object. It is supported whenever OpenGL is Panda's rendering engine, and GLCanvas is available in wx. """ diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000000..85a2d94031 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,13 @@ +[mypy] +explicit_package_bases = True +exclude = /(dist|directscripts)/ +warn_unused_ignores = True + +[mypy-panda3d.*] +ignore_missing_imports = True + +[mypy-wx.*] +ignore_missing_imports = True + +[mypy-Pmw.*] +ignore_missing_imports = True diff --git a/tests/run_mypy.py b/tests/run_mypy.py new file mode 100644 index 0000000000..df27d80cda --- /dev/null +++ b/tests/run_mypy.py @@ -0,0 +1,25 @@ +import os +import pathlib +import shutil +import subprocess +import tempfile + + +def main(): + root = pathlib.Path(__file__).parent.parent + direct_src = root / 'direct' / 'src' + mypy_config = root / 'mypy.ini' + with tempfile.TemporaryDirectory() as temp_dir: + os.environ['MYPYPATH'] = temp_dir + direct_copy = pathlib.Path(temp_dir, 'direct') + shutil.copytree(direct_src, direct_copy) + subprocess.run([ + 'mypy', + str(direct_copy), + '--config-file', + str(mypy_config), + ]) + + +if __name__ == '__main__': + main()