Skip to content

Commit eb7329b

Browse files
committed
Type hinting and janitor work
Restructured the message module to ensure outgoing and incoming messages are clearly separated. Furthermore, addresses of messages are now more strictly bound in case the protocol defines that a message can only be sent to one specific participant (server, client, initiator, responder). All message properties have been refactored to be `NewType`s. Cleaned up the `Path` class which should now be both a tiny bit more performant and use less memory. Further changes: Add mypy type checker to Travis. Remove dead code in the message module and its dependencies that is only required for a client. All usages of `asyncio.ensure_future` have been replaced by `loop.create_task`, resolves #95 (and made the type annotations easier).
1 parent 2b8bc21 commit eb7329b

27 files changed

+1778
-1194
lines changed

.travis.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,13 @@ install:
6767
- "pip install .[dev]"
6868
- pip install codecov
6969

70-
# Run flake8, isort, check docs & tests
70+
# Run flake8, isort, mypy, check docs & tests
7171
script:
7272
- >
7373
if [[ "$TRAVIS_PYTHON_VERSION" != "pypy3" ]]; then
7474
flake8 . || travis_terminate 1;
7575
isort -rc -c . || (isort -rc -df . && return 1) || travis_terminate 1;
76+
MYPYPATH=${PWD}/stubs mypy saltyrtc examples || travis_terminate 1;
7677
fi
7778
- python setup.py checkdocs
7879
- >

MANIFEST.in

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ include README.rst
44
recursive-include docs *
55
prune docs/_build
66
recursive-include examples *
7-
recursive-include tests *
7+
recursive-include stubs *
8+
recursive-include tests *

README.rst

+14-13
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,20 @@ Prerequisites
1717

1818
.. code-block:: bash
1919
20-
$ sudo apt-get install python3 python3-pip
20+
sudo apt-get install python3 python3-pip
2121
2222
We recommend using `venv`_ to create an isolated Python environment:
2323

2424
.. code-block:: bash
2525
26-
$ pyvenv venv
26+
pyvenv venv
2727
2828
You can switch into the created virtual environment *venv* by running
2929
this command:
3030

3131
.. code-block:: bash
3232
33-
$ source venv/bin/activate
33+
source venv/bin/activate
3434
3535
While the virtual environment is active, all packages installed using
3636
``pip`` will be installed into this environment.
@@ -39,7 +39,7 @@ To deactivate the virtual environment, just run:
3939

4040
.. code-block:: bash
4141
42-
$ deactivate
42+
deactivate
4343
4444
If you want easier handling of your virtualenvs, you might also want to
4545
take a look at `virtualenvwrapper`_.
@@ -53,7 +53,7 @@ Install the module by running:
5353

5454
.. code-block:: bash
5555
56-
$ pip install saltyrtc.server
56+
pip install saltyrtc.server
5757
5858
The dependency ``libnacl`` will be installed automatically. However, you
5959
may need to install `libsodium`_ for ``libnacl`` to work.
@@ -67,7 +67,7 @@ command to see usage information:
6767

6868
.. code-block:: bash
6969
70-
$ saltyrtc-server --help
70+
saltyrtc-server --help
7171
7272
Contributing
7373
************
@@ -77,19 +77,20 @@ optional ``dev`` requirements of the project in an editable environment:
7777

7878
.. code-block:: bash
7979
80-
$ git clone https://github.com/saltyrtc/saltyrtc-server-python.git
81-
$ cd saltyrtc-server-python
82-
$ pip install -e .[dev]
80+
git clone https://github.com/saltyrtc/saltyrtc-server-python.git
81+
cd saltyrtc-server-python
82+
pip install -e .[dev]
8383
8484
Before creating a pull request, it is recommended to run the following
8585
commands to check for code style violations (``flake8``), optimise
86-
imports (``isort``) and run the project's tests:
86+
imports (``isort``), do a static type analysis and run the project's tests:
8787

8888
.. code-block:: bash
8989
90-
$ flake8 .
91-
$ isort -rc .
92-
$ py.test
90+
flake8 .
91+
isort -rc .
92+
MYPYPATH=${PWD}/stubs mypy saltyrtc examples
93+
py.test
9394
9495
Reporting Security Issues
9596
*************************

RELEASING.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Signing key: https://lgrahl.de/pub/pgp-key.txt
88
```bash
99
flake8 .
1010
isort -rc -c . || isort -rc -df
11+
MYPYPATH=${PWD}/stubs mypy saltyrtc examples
1112
py.test
1213
```
1314

examples/debug.py

+21-10
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,61 @@
11
import asyncio
22
import os
3+
import ssl # noqa
34
import sys
5+
from typing import Any # noqa
6+
from typing import List # noqa
7+
from typing import Optional
48

59
import logbook.more
610

711
import saltyrtc.server
12+
from saltyrtc.server.typing import Coroutine # noqa
13+
from saltyrtc.server.typing import ServerSecretPermanentKey # noqa
814

915

10-
def env(name, default=None):
11-
return os.environ.get(name, default)
16+
def env(name: str, default: Optional[str] = None) -> Optional[str]:
17+
try:
18+
return os.environ[name]
19+
except KeyError:
20+
return default
1221

1322

14-
def require_env(name):
23+
def require_env(name: str) -> str:
1524
value = env(name)
1625
if value is None:
1726
print("Missing '{}' env variable".format(name))
1827
sys.exit(1)
1928
return value
2029

2130

22-
def main():
31+
def main() -> None:
2332
"""
2433
Run the SaltyRTC server until Ctrl+C has been pressed.
2534
"""
2635
loop = asyncio.get_event_loop()
2736

2837
# Create SSL context
38+
ssl_context = None # type: Optional[ssl.SSLContext]
2939
if env('SALTYRTC_DISABLE_TLS') != 'yes-and-i-know-what-im-doing':
3040
ssl_context = saltyrtc.server.create_ssl_context(
3141
certfile=require_env('SALTYRTC_TLS_CERT'),
3242
keyfile=require_env('SALTYRTC_TLS_KEY'),
3343
dh_params_file=require_env('SALTYRTC_DH_PARAMS'),
3444
)
35-
else:
36-
ssl_context = None
3745

3846
# Get permanent key
47+
permanent_keys = None # type: Optional[List[ServerSecretPermanentKey]]
3948
if env('SALTYRTC_DISABLE_SERVER_PERMANENT_KEY') != 'yes-and-i-know-what-im-doing':
4049
permanent_keys = [saltyrtc.server.load_permanent_key(
4150
require_env('SALTYRTC_SERVER_PERMANENT_KEY'))]
42-
else:
43-
permanent_keys = None
4451

4552
# Start server
46-
port = int(env('SALTYRTC_PORT', '8765'))
47-
coroutine = saltyrtc.server.serve(ssl_context, permanent_keys, port=port)
53+
port_str = env('SALTYRTC_PORT', '8765')
54+
assert port_str is not None
55+
port = int(port_str)
56+
coroutine = saltyrtc.server.serve(
57+
ssl_context, permanent_keys, port=port
58+
) # type: Coroutine[Any, Any, saltyrtc.server.Server]
4859
server = loop.run_until_complete(coroutine)
4960

5061
# Wait until Ctrl+C has been pressed

examples/restartable.py

+24-13
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
import asyncio
22
import os
33
import signal
4+
import ssl # noqa
45
import sys
6+
from typing import Any # noqa
7+
from typing import List # noqa
8+
from typing import Optional
59

610
import logbook.more
711

812
import saltyrtc.server
13+
from saltyrtc.server.typing import Coroutine # noqa
14+
from saltyrtc.server.typing import ServerSecretPermanentKey # noqa
915

1016

11-
def env(name, default=None):
12-
return os.environ.get(name, default)
17+
def env(name: str, default: Optional[str] = None) -> Optional[str]:
18+
try:
19+
return os.environ[name]
20+
except KeyError:
21+
return default
1322

1423

15-
def require_env(name):
24+
def require_env(name: str) -> str:
1625
value = env(name)
1726
if value is None:
1827
print("Missing '{}' env variable".format(name))
1928
sys.exit(1)
2029
return value
2130

2231

23-
def main():
32+
def main() -> None:
2433
"""
2534
Run the SaltyRTC server until Ctrl+C has been pressed.
2635
@@ -31,32 +40,34 @@ def main():
3140

3241
while True:
3342
# Create SSL context
43+
ssl_context = None # type: Optional[ssl.SSLContext]
3444
if env('SALTYRTC_DISABLE_TLS') != 'yes-and-i-know-what-im-doing':
3545
ssl_context = saltyrtc.server.create_ssl_context(
3646
certfile=require_env('SALTYRTC_TLS_CERT'),
3747
keyfile=require_env('SALTYRTC_TLS_KEY'),
3848
dh_params_file=require_env('SALTYRTC_DH_PARAMS'),
3949
)
40-
else:
41-
ssl_context = None
4250

4351
# Get permanent key
52+
permanent_keys = None # type: Optional[List[ServerSecretPermanentKey]]
4453
if env('SALTYRTC_DISABLE_SERVER_PERMANENT_KEY') != 'yes-and-i-know-what-im-doing':
4554
permanent_keys = [saltyrtc.server.load_permanent_key(
4655
require_env('SALTYRTC_SERVER_PERMANENT_KEY'))]
47-
else:
48-
permanent_keys = None
4956

5057
# Start server
51-
port = int(env('SALTYRTC_PORT', '8765'))
52-
coroutine = saltyrtc.server.serve(ssl_context, permanent_keys, port=port)
58+
port_str = env('SALTYRTC_PORT', '8765')
59+
assert port_str is not None
60+
port = int(port_str)
61+
coroutine = saltyrtc.server.serve(
62+
ssl_context, permanent_keys, port=port
63+
) # type: Coroutine[Any, Any, saltyrtc.server.Server]
5364
server = loop.run_until_complete(coroutine)
5465

5566
# Restart server on HUP signal
56-
restart_signal = asyncio.Future(loop=loop)
67+
restart_signal = asyncio.Future(loop=loop) # type: asyncio.Future[None]
5768

58-
def _restart_signal_handler(*_):
59-
restart_signal.set_result(True)
69+
def _restart_signal_handler(*_: None) -> None:
70+
restart_signal.set_result(None)
6071

6172
# Register restart server routine
6273
loop.add_signal_handler(signal.SIGHUP, _restart_signal_handler)

saltyrtc/server/__init__.py

+5-12
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,23 @@
44
"""
55
import itertools
66

7-
# noinspection PyUnresolvedReferences
8-
from .exception import * # noqa
9-
# noinspection PyUnresolvedReferences
107
from .common import * # noqa
11-
# noinspection PyUnresolvedReferences
8+
from .events import * # noqa
9+
from .exception import * # noqa
1210
from .message import * # noqa
13-
# noinspection PyUnresolvedReferences
1411
from .protocol import * # noqa
15-
# noinspection PyUnresolvedReferences
1612
from .server import * # noqa
17-
# noinspection PyUnresolvedReferences
1813
from .util import * # noqa
19-
# noinspection PyUnresolvedReferences
20-
from .events import * # noqa
2114

2215
__all__ = tuple(itertools.chain(
23-
('bin',),
24-
exception.__all__, # noqa
16+
('bin', 'typing'),
2517
common.__all__, # noqa
18+
events.__all__, # noqa
19+
exception.__all__, # noqa
2620
message.__all__, # noqa
2721
protocol.__all__, # noqa
2822
server.__all__, # noqa
2923
util.__all__, # noqa
30-
events.__all__, # noqa
3124
))
3225

3326
__author__ = 'Lennart Grahl <[email protected]>'

0 commit comments

Comments
 (0)