mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-19 21:37:57 +08:00
efro.message tidying and language updates
This commit is contained in:
parent
638e428883
commit
f368cbf30f
@ -420,7 +420,7 @@
|
||||
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/14/f1/4f2995d78fc20dd79dfb39c5d554",
|
||||
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/57/ac/6ed0caecd25dc23688debed24c45",
|
||||
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/32/08/38dac4a79ab2acee76a75d32a310",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/1f/21/0f8b5de13f6bd5fb1e13564d7c58",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/e4/48/6648ea4178c12d6e25ed3a53f628",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/0f/0e/7184059414320d32104463e41038",
|
||||
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/e2/58/c2c5964370df118c51528dc4bfa2",
|
||||
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/28/96/397e5c164a595c2b6c2d3eb2d4f1",
|
||||
@ -436,11 +436,11 @@
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/0a/ec/f6665a696238275c806e7a0b1d0d",
|
||||
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/ff/08/0d32d1babc60fdebd39def8b51da",
|
||||
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/63/f0/cc8dd75a100f7d58000a361ca160",
|
||||
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/cf/2b/23acc62ab35c4763a9cfe23495dc",
|
||||
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/2d/e5/3737c6c3979cf381321c5472bea5",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/87/e5/a10ddd73cfb7996bbd576032db6a",
|
||||
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/dd/97/42d117db366ad4584eb8c58d191e",
|
||||
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/26/8d/bf9cc8db2cc71b69e789898e1093",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/d8/b7/9098f0cb25088d233541490e3e68",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/2d/d5/661c050696d5a2e70e678054b9e7",
|
||||
"assets/build/ba_data/data/languages/polish.json": "https://files.ballistica.net/cache/ba1/2e/17/fb3e7ed77fa54427b434b1791793",
|
||||
"assets/build/ba_data/data/languages/portuguese.json": "https://files.ballistica.net/cache/ba1/fe/6d/751277bc6b704d4f2a54cf1a9cfa",
|
||||
"assets/build/ba_data/data/languages/romanian.json": "https://files.ballistica.net/cache/ba1/82/12/57bf144e12be229a9b70da9c45cb",
|
||||
@ -451,8 +451,8 @@
|
||||
"assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/50/9f/be006ba19be6a69a57837eb6dca0",
|
||||
"assets/build/ba_data/data/languages/thai.json": "https://files.ballistica.net/cache/ba1/dd/de/c197fa9aff42e4422bc66b95ad88",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/65/e4/b9308f15437972209b4d3fce7abd",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/c3/61/d5bcf2bcad50104b26d22d3365a4",
|
||||
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/4b/da/7e444f86c768aee70779a0f7a28f",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/8f/42/56f3ebcc6005f382449c1c2422fd",
|
||||
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/4f/cc/285443e3e8e65a318df338bbc7f7",
|
||||
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/8b/65/adfbe450da3f61677bd909fff707",
|
||||
"assets/build/ba_data/data/maps/big_g.json": "https://files.ballistica.net/cache/ba1/47/0a/a617cc85d927b576c4e6fc1091ed",
|
||||
"assets/build/ba_data/data/maps/bridgit.json": "https://files.ballistica.net/cache/ba1/03/4b/57ee9b42854b26f23f81bd8c58ef",
|
||||
|
||||
2
.idea/dictionaries/ericf.xml
generated
2
.idea/dictionaries/ericf.xml
generated
@ -1600,6 +1600,7 @@
|
||||
<w>outvalue</w>
|
||||
<w>ouya</w>
|
||||
<w>overloadsigs</w>
|
||||
<w>ovld</w>
|
||||
<w>packagedir</w>
|
||||
<w>packagedirs</w>
|
||||
<w>packagename</w>
|
||||
@ -2356,6 +2357,7 @@
|
||||
<w>touchpad</w>
|
||||
<w>tournamententry</w>
|
||||
<w>tournamentscores</w>
|
||||
<w>tpimport</w>
|
||||
<w>tpimportex</w>
|
||||
<w>tpimports</w>
|
||||
<w>tplayer</w>
|
||||
|
||||
@ -767,6 +767,7 @@
|
||||
<w>outval</w>
|
||||
<w>outvalue</w>
|
||||
<w>ouya</w>
|
||||
<w>ovld</w>
|
||||
<w>parameteriv</w>
|
||||
<w>passcode</w>
|
||||
<w>pausable</w>
|
||||
@ -1075,6 +1076,7 @@
|
||||
<w>touchpad</w>
|
||||
<w>toucs</w>
|
||||
<w>toutf</w>
|
||||
<w>tpimport</w>
|
||||
<w>tpimportex</w>
|
||||
<w>tpimports</w>
|
||||
<w>tracebacks</w>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<h4><em>last updated on 2021-09-24 for Ballistica version 1.6.5 build 20393</em></h4>
|
||||
<h4><em>last updated on 2021-09-27 for Ballistica version 1.6.5 build 20393</em></h4>
|
||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||
<hr>
|
||||
|
||||
@ -6,7 +6,7 @@ from __future__ import annotations
|
||||
|
||||
import os
|
||||
import asyncio
|
||||
from typing import TYPE_CHECKING, overload
|
||||
from typing import TYPE_CHECKING, overload, Union
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pytest
|
||||
@ -19,7 +19,7 @@ from efro.message import (Message, Response, MessageProtocol, MessageSender,
|
||||
BoundMessageReceiver)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import List, Type, Any, Callable, Union, Optional, Awaitable
|
||||
from typing import List, Type, Any, Callable, Optional, Awaitable
|
||||
|
||||
|
||||
@ioprepped
|
||||
|
||||
@ -75,6 +75,8 @@ class EmptyResponse(Response):
|
||||
|
||||
# TODO: could allow handlers to deal in raw values for these
|
||||
# types similar to how we allow None in place of EmptyResponse.
|
||||
# Though not sure if they are widely used enough to warrant the
|
||||
# extra code complexity.
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class BoolResponse(Response):
|
||||
@ -83,6 +85,14 @@ class BoolResponse(Response):
|
||||
value: Annotated[bool, IOAttrs('v')]
|
||||
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class StringResponse(Response):
|
||||
"""A simple string value response."""
|
||||
|
||||
value: Annotated[str, IOAttrs('v')]
|
||||
|
||||
|
||||
class MessageProtocol:
|
||||
"""Wrangles a set of message types, formats, and response types.
|
||||
Both endpoints must be using a compatible Protocol for communication
|
||||
@ -154,7 +164,7 @@ class MessageProtocol:
|
||||
|
||||
_reg_if_not(ErrorResponse, -1)
|
||||
_reg_if_not(EmptyResponse, -2)
|
||||
_reg_if_not(BoolResponse, -3)
|
||||
# _reg_if_not(BoolResponse, -3)
|
||||
|
||||
# Some extra-thorough validation in debug mode.
|
||||
if __debug__:
|
||||
@ -173,7 +183,8 @@ class MessageProtocol:
|
||||
assert issubclass(cls, Response)
|
||||
if cls not in self.response_ids_by_type:
|
||||
raise ValueError(f'Possible response type {cls}'
|
||||
f' was not included in response_types.')
|
||||
f' needs to be included in response_types'
|
||||
f' for this protocol.')
|
||||
|
||||
# Make sure all registered types have unique base names.
|
||||
# We can take advantage of this to generate cleaner looking
|
||||
@ -270,46 +281,78 @@ class MessageProtocol:
|
||||
|
||||
def _get_module_header(self, part: str) -> str:
|
||||
"""Return common parts of generated modules."""
|
||||
# pylint: disable=too-many-locals, too-many-branches
|
||||
import textwrap
|
||||
tpimports: Dict[str, List[str]] = {}
|
||||
imports: Dict[str, List[str]] = {}
|
||||
|
||||
single_message_type = len(self.message_ids_by_type) == 1
|
||||
|
||||
# Always import messages
|
||||
for msgtype in list(self.message_ids_by_type) + [Message]:
|
||||
imports.setdefault(msgtype.__module__, []).append(msgtype.__name__)
|
||||
tpimports.setdefault(msgtype.__module__,
|
||||
[]).append(msgtype.__name__)
|
||||
for rsp_tp in list(self.response_ids_by_type) + [Response]:
|
||||
# Skip these as they don't actually show up in code.
|
||||
if rsp_tp is EmptyResponse or rsp_tp is ErrorResponse:
|
||||
continue
|
||||
imports.setdefault(rsp_tp.__module__, []).append(rsp_tp.__name__)
|
||||
importlines2 = ''
|
||||
if (single_message_type and part == 'sender'
|
||||
and rsp_tp is not Response):
|
||||
# We need to cast to the single supported response type
|
||||
# in this case so need response types at runtime.
|
||||
imports.setdefault(rsp_tp.__module__,
|
||||
[]).append(rsp_tp.__name__)
|
||||
else:
|
||||
tpimports.setdefault(rsp_tp.__module__,
|
||||
[]).append(rsp_tp.__name__)
|
||||
|
||||
import_lines = ''
|
||||
tpimport_lines = ''
|
||||
|
||||
for module, names in sorted(imports.items()):
|
||||
jnames = ', '.join(names)
|
||||
line = f'from {module} import {jnames}'
|
||||
if len(line) > 79:
|
||||
# Recreate in a wrapping-friendly form.
|
||||
line = f'from {module} import ({jnames})'
|
||||
importlines2 += f' {line}\n'
|
||||
import_lines += f'{line}\n'
|
||||
for module, names in sorted(tpimports.items()):
|
||||
jnames = ', '.join(names)
|
||||
line = f'from {module} import {jnames}'
|
||||
if len(line) > 75: # Account for indent
|
||||
# Recreate in a wrapping-friendly form.
|
||||
line = f'from {module} import ({jnames})'
|
||||
tpimport_lines += f'{line}\n'
|
||||
|
||||
if part == 'sender':
|
||||
importlines1 = (
|
||||
'from efro.message import MessageSender, BoundMessageSender')
|
||||
tpimportex = ''
|
||||
import_lines += ('from efro.message import MessageSender,'
|
||||
' BoundMessageSender')
|
||||
tpimport_typing_extras = ''
|
||||
else:
|
||||
importlines1 = ('from efro.message import MessageReceiver,'
|
||||
' BoundMessageReceiver')
|
||||
tpimportex = ', Awaitable'
|
||||
if single_message_type:
|
||||
import_lines += ('from efro.message import (MessageReceiver,'
|
||||
' BoundMessageReceiver, Message, Response)')
|
||||
else:
|
||||
import_lines += ('from efro.message import MessageReceiver,'
|
||||
' BoundMessageReceiver')
|
||||
tpimport_typing_extras = ', Awaitable'
|
||||
|
||||
ovld = ', overload' if not single_message_type else ''
|
||||
tpimport_lines = textwrap.indent(tpimport_lines, ' ')
|
||||
out = ('# Released under the MIT License. See LICENSE for details.\n'
|
||||
f'#\n'
|
||||
f'"""Auto-generated {part} module. Do not edit by hand."""\n'
|
||||
f'\n'
|
||||
f'from __future__ import annotations\n'
|
||||
f'\n'
|
||||
f'from typing import TYPE_CHECKING, overload\n'
|
||||
f'from typing import TYPE_CHECKING{ovld}\n'
|
||||
f'\n'
|
||||
f'{importlines1}\n'
|
||||
f'{import_lines}\n'
|
||||
f'\n'
|
||||
f'if TYPE_CHECKING:\n'
|
||||
f' from typing import Union, Any, Optional, Callable'
|
||||
f'{tpimportex}\n'
|
||||
f'{importlines2}'
|
||||
f'{tpimport_typing_extras}\n'
|
||||
f'{tpimport_lines}'
|
||||
f'\n'
|
||||
f'\n')
|
||||
return out
|
||||
@ -324,6 +367,8 @@ class MessageProtocol:
|
||||
# pylint: disable=too-many-locals
|
||||
import textwrap
|
||||
|
||||
msgtypes = list(self.message_ids_by_type.keys())
|
||||
|
||||
ppre = '_' if private else ''
|
||||
out = self._get_module_header('sender')
|
||||
ccind = textwrap.indent(protocol_create_code, ' ')
|
||||
@ -345,16 +390,12 @@ class MessageProtocol:
|
||||
f'class {ppre}Bound{basename}(BoundMessageSender):\n'
|
||||
f' """Protocol-specific bound sender."""\n')
|
||||
|
||||
# Define handler() overloads for all registered message types.
|
||||
msgtypes = [
|
||||
t for t in self.message_ids_by_type if issubclass(t, Message)
|
||||
]
|
||||
|
||||
def _filt_tp_name(rtype: Type[Response]) -> str:
|
||||
# We accept None to equal EmptyResponse so reflect that
|
||||
# in the type annotation.
|
||||
return 'None' if rtype is EmptyResponse else rtype.__name__
|
||||
|
||||
# Define handler() overloads for all registered message types.
|
||||
if msgtypes:
|
||||
for async_pass in False, True:
|
||||
if async_pass and not enable_async_sends:
|
||||
@ -422,6 +463,7 @@ class MessageProtocol:
|
||||
|
||||
desc = 'asynchronous' if is_async else 'synchronous'
|
||||
ppre = '_' if private else ''
|
||||
msgtypes = list(self.message_ids_by_type.keys())
|
||||
out = self._get_module_header('receiver')
|
||||
ccind = textwrap.indent(protocol_create_code, ' ')
|
||||
out += (f'class {ppre}{basename}(MessageReceiver):\n'
|
||||
@ -442,9 +484,6 @@ class MessageProtocol:
|
||||
f'obj, self)\n')
|
||||
|
||||
# Define handler() overloads for all registered message types.
|
||||
msgtypes = [
|
||||
t for t in self.message_ids_by_type if issubclass(t, Message)
|
||||
]
|
||||
|
||||
def _filt_tp_name(rtype: Type[Response]) -> str:
|
||||
# We accept None to equal EmptyResponse so reflect that
|
||||
@ -539,7 +578,7 @@ class MessageSender:
|
||||
class MyClass:
|
||||
msg = MyMessageSender(some_protocol)
|
||||
|
||||
@msg.sendmethod
|
||||
@msg.send_method
|
||||
def send_raw_message(self, message: str) -> str:
|
||||
# Actually send the message here.
|
||||
|
||||
@ -676,10 +715,9 @@ class MessageReceiver:
|
||||
The message type handled by the call is determined by its
|
||||
type annotation.
|
||||
"""
|
||||
# pylint: disable=too-many-locals
|
||||
# TODO: can use types.GenericAlias in 3.9.
|
||||
from typing import _GenericAlias # type: ignore
|
||||
from typing import Union, get_type_hints, get_args
|
||||
from typing import get_type_hints, get_args
|
||||
|
||||
sig = inspect.getfullargspec(call)
|
||||
|
||||
@ -700,7 +738,10 @@ class MessageReceiver:
|
||||
# Check annotation types to determine what message types we handle.
|
||||
# Return-type annotation can be a Union, but we probably don't
|
||||
# have it available at runtime. Explicitly pull it in.
|
||||
anns = get_type_hints(call, localns={'Union': Union})
|
||||
# UPDATE: we've updated our pylint filter to where we should
|
||||
# have all annotations available.
|
||||
# anns = get_type_hints(call, localns={'Union': Union})
|
||||
anns = get_type_hints(call)
|
||||
|
||||
msgtype = anns.get('msg')
|
||||
if not isinstance(msgtype, type):
|
||||
@ -758,11 +799,12 @@ class MessageReceiver:
|
||||
if issubclass(msgtype, Response):
|
||||
continue
|
||||
if msgtype not in self._handlers:
|
||||
msg = (f'Protocol message {msgtype} not handled'
|
||||
f' by receiver.')
|
||||
msg = (f'Protocol message type {msgtype} is not handled'
|
||||
f' by receiver type {type(self)}.')
|
||||
if warn_only:
|
||||
logging.warning(msg)
|
||||
raise TypeError(msg)
|
||||
else:
|
||||
raise TypeError(msg)
|
||||
|
||||
def _decode_incoming_message(self,
|
||||
msg: str) -> Tuple[Message, Type[Message]]:
|
||||
|
||||
@ -123,17 +123,20 @@ def func_annotations_filter(node: nc.NodeNG) -> nc.NodeNG:
|
||||
|
||||
# Wipe out argument annotations.
|
||||
|
||||
# Special-case: functools.singledispatch and ba.dispatchmethod *do*
|
||||
# Special-case: certain function decorators *do*
|
||||
# evaluate annotations at runtime so we want to leave theirs intact.
|
||||
# Lets just look for a @XXX.register decorator used by both I guess.
|
||||
# This includes functools.singledispatch, ba.dispatchmethod, and
|
||||
# efro.MessageReceiver.
|
||||
# Lets just look for a @XXX.register or @XXX.handler decorators for
|
||||
# now; can get more specific if we get false positives.
|
||||
if node.decorators is not None:
|
||||
for dnode in node.decorators.nodes:
|
||||
if (isinstance(dnode, astroid.nodes.Name)
|
||||
and dnode.name in ('dispatchmethod', 'singledispatch')):
|
||||
and dnode.name in {'dispatchmethod', 'singledispatch'}):
|
||||
return node # Leave annotations intact.
|
||||
|
||||
if (isinstance(dnode, astroid.nodes.Attribute)
|
||||
and dnode.attrname == 'register'):
|
||||
and dnode.attrname in {'register', 'handler'}):
|
||||
return node # Leave annotations intact.
|
||||
|
||||
node.args.annotations = [None for _ in node.args.args]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user