Skip to content

Commit c6f718f

Browse files
committed
Simplify interactive start.
The main change in this mega commit is removing recently added `start` method. Now there's only `serve` for interactive usage. Users can run it in a thread if needed, handling that in the server turned out to be too complicated compared to the benefits.
1 parent f69cf34 commit c6f718f

File tree

10 files changed

+275
-265
lines changed

10 files changed

+275
-265
lines changed

README.rst

Lines changed: 103 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ Python Remote Server for Robot Framework
22
========================================
33

44
`Robot Framework`_ remote servers allow hosting test libraries on different
5-
processes or machines than Robot Framework itself is running on. See the
6-
general `remote library interface documentation`_ for more information about
7-
the remote interface as well as for a list of remote server implementations
8-
in other programming languages.
5+
processes or machines than Robot Framework itself is running on. This project
6+
implements a generic remote server using the Python_ programming language.
7+
See the general `remote library interface documentation`_ for more information
8+
about the remote interface as well as for a list of remote server
9+
implementations in other programming languages.
910

1011
This project is hosted in GitHub_ and downloads are available in PyPI_.
1112

@@ -21,8 +22,9 @@ Supported Python versions
2122
-------------------------
2223

2324
This remote server is implemented with Python_ and supports also Jython_ (JVM),
24-
IronPython_ (.NET) and PyPy_. Remote server 1.1 and newer support Python 2.6,
25-
2.7, 3.3, and newer. Remote server 1.0 series supports Python versions 2.2-2.7.
25+
IronPython_ (.NET) and PyPy_. Remote server version 1.1 and newer support
26+
Python 2.6, 2.7, 3.3, and newer. Remote server 1.0 series supports Python
27+
versions 2.2-2.7.
2628

2729
.. _Python: http://python.org
2830
.. _Jython: http://jython.org
@@ -32,15 +34,15 @@ IronPython_ (.NET) and PyPy_. Remote server 1.1 and newer support Python 2.6,
3234
Supported library APIs
3335
----------------------
3436

35-
Starting from Remote server 1.1, Robot Framework's normal `static, hybrid and
36-
dynamic library APIs`__ are all supported. This includes setting custom name
37-
and tags for keywords using the `robot.api.deco.keyword`__ decorator.
38-
Earlier versions support only the static and hybrid APIs and do not support
39-
the keyword decorator.
37+
Starting from Remote server version 1.1, Robot Framework's standard `static,
38+
hybrid and dynamic library APIs`__ are all supported. This includes setting
39+
custom name and tags for keywords using the `robot.api.deco.keyword`__
40+
decorator. Earlier versions support only the static and hybrid APIs and do
41+
not support the keyword decorator.
4042

4143
For most parts these APIs work exactly like when using with Robot Framework
4244
normally. There main limitation is that logging using ``robot.api.logger`` or
43-
Python's ``logging`` module `is not supported`__.
45+
Python's ``logging`` module `is currently not supported`__.
4446

4547
__ http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#creating-test-libraries
4648
__ http://robot-framework.readthedocs.io/en/latest/autodoc/robot.api.html#robot.api.deco.keyword
@@ -54,43 +56,28 @@ The easiest installation approach is using `pip`_::
5456
pip install robotremoteserver
5557

5658
Alternatively you can download the source distribution from PyPI_, extract it
57-
and install the server using::
59+
and install the remote server using::
5860

5961
python setup.py install
6062

6163
.. _`pip`: http://www.pip-installer.org
6264

63-
Starting remote server
64-
----------------------
65-
66-
The remote server can be started by simply creating an instance of the server
67-
and passing a test library instance or module to it:
68-
69-
.. sourcecode:: python
70-
71-
from robotremoteserver import RobotRemoteServer
72-
from mylibrary import MyLibrary
73-
74-
RobotRemoteServer(MyLibrary())
75-
76-
By default the server listens to address 127.0.0.1 and port 8270. See the next
77-
section for information about configuring the server.
78-
7965
Remote server configuration
8066
---------------------------
8167

82-
The remote server accepts following configuration parameters:
68+
The remote server is implemented as a class ``RobotRemoteServer`` and it
69+
accepts the following configuration parameters when it is initialized:
8370

8471
===================== ================= ========================================
8572
Argument Default Explanation
8673
===================== ================= ========================================
8774
``library`` Test library instance or module to host. Mandatory argument.
8875
``host`` ``'127.0.0.1'`` Address to listen. Use ``'0.0.0.0'`` to listen to all available interfaces.
8976
``port`` ``8270`` Port to listen. Use ``0`` to select a free port automatically. Can be given as an integer or as a string.
90-
``port_file`` ``None`` File to write port that is used. ``None`` means no such file is written.
77+
``port_file`` ``None`` File to write the port that is used. ``None`` (default) means no such file is written.
9178
``allow_stop`` ``'DEPRECATED'`` DEPRECATED. User ``allow_remote_stop`` instead.
92-
``serve`` ``True`` If ``True``, start the server automatically and wait for it to be stopped. If ``False``, server can be started using ``serve`` or ``start`` methods. New in version 1.1.
93-
``allow_remote_stop`` ``True`` Allow/disallow stopping the server using ``Stop Remote Server`` keyword and ``stop_remote_server`` XML-RPC method. New in version 1.1.
79+
``serve`` ``True`` If ``True``, start the server automatically and wait for it to be stopped. If ``False``, server can be started using the ``serve`` method. New in version 1.1.
80+
``allow_remote_stop`` ``True`` Allow/disallow stopping the server remotely using ``Stop Remote Server`` keyword and ``stop_remote_server`` XML-RPC method. New in version 1.1.
9481
===================== ================= ========================================
9582

9683
Address and port that are used are printed to the console where the server is
@@ -99,9 +86,26 @@ useful when the server selects a free port automatically. Other tools can then
9986
easily read the active port from the file. If the file is removed prior to
10087
starting the server, tools can also wait until the file exists to know that
10188
the server is up and running. Starting from version 1.1, the server removes
102-
the port file automatically.
89+
the port file automatically when it is stopped.
10390

104-
Example:
91+
Starting remote server
92+
----------------------
93+
94+
The remote server can be started simply by creating an instance of the server
95+
and passing a test library instance or module to it:
96+
97+
.. sourcecode:: python
98+
99+
from robotremoteserver import RobotRemoteServer
100+
from mylibrary import MyLibrary
101+
102+
RobotRemoteServer(MyLibrary())
103+
104+
By default the server listens to address 127.0.0.1 and port 8270. As `discussed
105+
above`__, the remote server accepts various configuration parameters. Some of
106+
them are used by this example:
107+
108+
__ `Remote server configuration`_
105109

106110
.. sourcecode:: python
107111

@@ -111,77 +115,93 @@ Example:
111115
RobotRemoteServer(MyLibrary(), host='10.0.0.42', port=0,
112116
port_file='/tmp/remote-port.txt')
113117

114-
Starting from versoin 1.1, the server can also first be initialized and started
115-
afterwards:
118+
Starting from version 1.1, the server can be initialized without starting it by
119+
using the argument ``serve=False``. The server can then started afterwards by
120+
calling its ``serve`` method explicitly. This example is functionally
121+
equivalent to the example above:
116122

117123
.. sourcecode:: python
118124

119125
server = RobotRemoteServer(MyLibrary(), host='10.0.0.42', port=0,
120126
port_file='/tmp/remote-port.txt', serve=False)
121127
server.serve()
122128

123-
The above is totally equivalent to the earlier example and both of them result
124-
with the server starting and running until it is `explicitly stopped`__.
125-
Alternatively it is possible to `start the server on background`__.
129+
Starting server on background
130+
-----------------------------
126131

127-
__ `Stopping remote server`_
128-
__ `Starting server on background`_
132+
The main benefit of separately initializing and starting the server is that
133+
it makes it easier to start the server on a background thread. This is
134+
illustrated by the following example:
129135

130-
Stopping remote server
131-
----------------------
136+
.. sourcecode:: python
132137

133-
The remote server can be gracefully stopped using several different methods:
138+
import threading
139+
import time
134140

135-
- Hitting ``Ctrl-C`` on the console where the server is running. Does not work
136-
reliably with version 1.0 or earlier or if using Python 2.5 or older.
141+
from robotremoteserver import RobotRemoteServer
142+
from mylibrary import MyLibrary
137143

138-
- Sending the process ``SIGINT``, ``SIGTERM``, or ``SIGHUP`` signal. Does not
139-
work on Windows. Notice that with Jython you need to send the signal to the
140-
started Java process, not to the shell typically started by ``jython`` command.
144+
try:
145+
raw_input
146+
except NameError: # Python 3
147+
raw_input = input
141148

142-
- Using ``Stop Remote Server`` keyword.
149+
# Initialize server and start it in a thread.
150+
server = RobotRemoteServer(MyLibrary(), port=0, serve=False)
151+
server_thread = threading.Thread(target=server.serve)
152+
server_thread.start()
153+
# Wait for server to be activated and port to be bind.
154+
while server.server_port == 0:
155+
time.sleep(0.1)
156+
# Serve requests until user presses enter.
157+
raw_input('Press enter to stop the server.\n')
158+
server.stop()
159+
server_thread.join()
143160

144-
- Using ``stop_remote_server`` function in the XML-RPC interface.
161+
Servers started this way work mostly like servers started on the main thread.
162+
The main difference is that stopping the server gracefully using ``Ctrl-C``
163+
or signals is not supported automatically. The user must register signal
164+
handlers separately if needed.
145165

146-
- Running ``python -m robotremoteserver stop [uri]`` or using
147-
``stop_remote_server`` function similarly as when `testing is server running`_.
166+
Stopping remote server
167+
----------------------
148168

149-
- Calling ``stop`` method of the running server object.
169+
The remote server can be gracefully stopped using several different methods:
150170

151-
Using ``Stop Remote Server`` keyword, ``stop_remote_server`` XML-RPC function
152-
or stopping functionality provided by ``robotremoteserver`` itself can all be
153-
disabled by using ``allow_remote_stop=False`` when initializing the server.
171+
- Hitting ``Ctrl-C`` on the console where the server is running. Not supported
172+
automatically if the server is `started on a background thread`__.
154173

155-
Starting server on background
156-
-----------------------------
174+
- Sending the process ``SIGINT``, ``SIGTERM``, or ``SIGHUP`` signal. Does not
175+
work on Windows and not supported if the server is started on a background
176+
thread.
157177

158-
Sometimes it is useful to start the server on background and keep doing
159-
something else, like starting more servers, on the main thread. Starting
160-
from RobotRemoteServer 1.1 this can be accomplished easily:
178+
- Using ``Stop Remote Server`` keyword. Can be disabled by using
179+
``allow_remote_stop=False`` when `initializing the server`__.
161180

162-
.. sourcecode:: python
181+
- Using ``stop_remote_server`` function in the XML-RPC interface.
182+
Can be disabled with ``allow_remote_stop=False``.
163183

164-
from robotremoteserver import RobotRemoteServer
165-
from mylibrary import MyLibrary
184+
- Running ``python -m robotremoteserver stop [uri]`` which uses the
185+
aforementioned ``stop_remote_server`` XML-RPC function internally.
186+
Can be disabled with ``allow_remote_stop=False``.
166187

167-
server = RobotRemoteServer(MyLibrary(), port=0, serve=False)
168-
server.start()
169-
print('Remote server started on port %d.' % server.server_port)
170-
# Do something ...
171-
server.stop()
188+
- Using the ``stop_remote_server`` function provided by the
189+
``robotremoteserver`` module similarly as when `testing is server running`_.
190+
Uses the ``stop_remote_server`` XML-RPC function internally and
191+
can be disabled with ``allow_remote_stop=False``.
172192

173-
As the above example illustrates, the ``start`` method starts the server on
174-
background. When the server is started on background, none of the earlier
175-
methods to `stop the server`__ work. Instead the server can be stopped, as
176-
shown in the example, by using the ``stop`` method.
193+
- Calling ``stop`` method of the running server instance. Mainly useful when
194+
`running the server on background`__.
177195

178-
__ `Stopping remote server`_
196+
__ `Starting server on background`_
197+
__ `Remote server configuration`_
198+
__ `Starting server on background`_
179199

180200
Testing is server running
181201
-------------------------
182202

183-
Starting from version 1.0.1 , ``robotremoteserver`` module supports testing is
184-
a remote server running. This can be accomplished by running the module as
203+
Starting from version 1.0.1 , the ``robotremoteserver`` module supports testing
204+
is a remote server running. This can be accomplished by running the module as
185205
a script with ``test`` argument and an optional URI::
186206

187207
$ python -m robotremoteserver test
@@ -190,7 +210,7 @@ a script with ``test`` argument and an optional URI::
190210
No remote server running at http://10.0.0.42:57347.
191211

192212
Starting from version 1.1, ``robotremoteserver`` module contains function
193-
``stop_remote_server`` that can be used programmatically:
213+
``test_remote_server`` that can be used programmatically:
194214

195215
.. sourcecode:: python
196216

@@ -199,10 +219,10 @@ Starting from version 1.1, ``robotremoteserver`` module contains function
199219
if test_remote_server('http://localhost:8270'):
200220
print('Remote server running!')
201221

202-
``robotremoteserver`` can be also used to stop a remote server by using
203-
``stop`` argument on the command line or by using ``stop_remote_server``
204-
function programmatically. Testing and stopping should work also with
205-
other Robot Framework remote server implementations.
222+
The ``robotremoteserver`` module can be also used to stop a remote server by
223+
using ``stop`` argument on the command line or by using the
224+
``stop_remote_server`` function programmatically. Testing and stopping should
225+
work also with other Robot Framework remote server implementations.
206226

207227
Example
208228
-------

example/examplelibrary.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
from __future__ import print_function
44

55
import os
6+
import sys
7+
8+
from robotremoteserver import RobotRemoteServer
9+
610

711
try:
812
basestring
@@ -30,7 +34,4 @@ def strings_should_be_equal(self, str1, str2):
3034

3135

3236
if __name__ == '__main__':
33-
import sys
34-
from robotremoteserver import RobotRemoteServer
35-
3637
RobotRemoteServer(ExampleRemoteLibrary(), *sys.argv[1:])

0 commit comments

Comments
 (0)