Skip to content

Commit 3caa81c

Browse files
committed
remove factory classes
- collapse HubFactory, IPControllerApp into IPController - collapse EngineFactory, IPEngineApp into IPEngine - move apps into `subpackage.app` instead of all together in `.apps` - add deprecations so old config still works - eliminate SessionFactory, RegistrationFactory
1 parent 9fe65a5 commit 3caa81c

File tree

26 files changed

+1212
-1285
lines changed

26 files changed

+1212
-1285
lines changed

docs/source/reference/db.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ or in your :file:`ipcontroller_config.py`:
2323

2424
.. sourcecode:: python
2525

26-
c.HubFactory.db_class = "NoDB"
27-
c.HubFactory.db_class = "DictDB" # default
28-
c.HubFactory.db_class = "MongoDB"
29-
c.HubFactory.db_class = "SQLiteDB"
26+
c.IPController.db_class = "NoDB"
27+
c.IPController.db_class = "DictDB" # default
28+
c.IPController.db_class = "MongoDB"
29+
c.IPController.db_class = "SQLiteDB"
3030

3131

3232
Using the Task Database

docs/source/tutorial/process.rst

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ matter which method you use to start your IPython cluster.
2929

3030
If you are running engines on multiple machines, you will likely need to instruct the
3131
controller to listen for connections on an external interface. This can be done by specifying
32-
the ``ip`` argument on the command-line, or the ``HubFactory.ip`` configurable in
32+
the ``ip`` argument on the command-line, or the ``IPController.ip`` configurable in
3333
:file:`ipcontroller_config.py`.
3434

3535
If your machines are on a trusted network, you can safely instruct the controller to listen
@@ -42,8 +42,8 @@ Or you can set the same behavior as the default by adding the following line to
4242

4343
.. sourcecode:: python
4444

45-
c.HubFactory.ip = '*'
46-
# c.HubFactory.location = 'controllerhost.tld'
45+
c.IPController.ip = '*'
46+
# c.IPController.location = 'controllerhost.tld'
4747

4848

4949
.. note::
@@ -78,7 +78,7 @@ hosts ``host1``-``hostn``. The following steps are then required:
7878

7979
1. Start the controller on ``host0`` by running :command:`ipcontroller` on
8080
``host0``. The controller must be instructed to listen on an interface visible
81-
to the engine machines, via the ``ip`` command-line argument or ``HubFactory.ip``
81+
to the engine machines, via the ``ip`` command-line argument or ``IPController.ip``
8282
in :file:`ipcontroller_config.py`.
8383
2. Move the JSON file (:file:`ipcontroller-engine.json`) created by the
8484
controller from ``host0`` to hosts ``host1``-``hostn``.
@@ -364,7 +364,7 @@ connections on all its interfaces, by adding in :file:`ipcontroller_config`:
364364

365365
.. sourcecode:: python
366366

367-
c.HubFactory.ip = '*'
367+
c.IPController.ip = '*'
368368

369369
You can now run the cluster with::
370370

@@ -532,14 +532,14 @@ slightly more complicated, but the underlying ideas are the same:
532532

533533
1. Start the controller on a host using :command:`ipcontroller`. The controller must be
534534
instructed to listen on an interface visible to the engine machines, via the ``ip``
535-
command-line argument or ``HubFactory.ip`` in :file:`ipcontroller_config.py`::
535+
command-line argument or ``IPController.ip`` in :file:`ipcontroller_config.py`::
536536

537537
$ ipcontroller --ip=192.168.1.16
538538

539539
.. sourcecode:: python
540540

541541
# in ipcontroller_config.py
542-
HubFactory.ip = '192.168.1.16'
542+
IPController.ip = '192.168.1.16'
543543

544544
2. Copy :file:`ipcontroller-engine.json` from :file:`IPYTHONDIR/profile_<name>/security` on
545545
the controller's host to the host where the engines will run.
@@ -618,15 +618,15 @@ the engines.
618618

619619
[controller.host] $ ipcontroller --ip=192.168.1.16
620620

621-
[IPControllerApp] Using existing profile dir: u'/Users/me/.ipython/profile_default'
622-
[IPControllerApp] Hub listening on tcp://192.168.1.16:63320 for registration.
623-
[IPControllerApp] Hub using DB backend: 'ipyparallel.controller.dictdb.DictDB'
624-
[IPControllerApp] hub::created hub
625-
[IPControllerApp] writing connection info to /Users/me/.ipython/profile_default/security/ipcontroller-client.json
626-
[IPControllerApp] writing connection info to /Users/me/.ipython/profile_default/security/ipcontroller-engine.json
627-
[IPControllerApp] task::using Python leastload Task scheduler
628-
[IPControllerApp] Heartmonitor started
629-
[IPControllerApp] Creating pid file: /Users/me/.ipython/profile_default/pid/ipcontroller.pid
621+
[IPController] Using existing profile dir: u'/Users/me/.ipython/profile_default'
622+
[IPController] Hub listening on tcp://192.168.1.16:63320 for registration.
623+
[IPController] Hub using DB backend: 'ipyparallel.controller.dictdb.DictDB'
624+
[IPController] hub::created hub
625+
[IPController] writing connection info to /Users/me/.ipython/profile_default/security/ipcontroller-client.json
626+
[IPController] writing connection info to /Users/me/.ipython/profile_default/security/ipcontroller-engine.json
627+
[IPController] task::using Python leastload Task scheduler
628+
[IPController] Heartmonitor started
629+
[IPController] Creating pid file: /Users/me/.ipython/profile_default/pid/ipcontroller.pid
630630
Scheduler started [leastload]
631631

632632
2. on each engine, fetch the connection file with scp::
@@ -711,15 +711,15 @@ Ports and addresses
711711
In many cases, you will want to configure the Controller's network identity. By default,
712712
the Controller listens only on loopback, which is the most secure but often impractical.
713713
To instruct the controller to listen on a specific interface, you can set the
714-
:attr:`HubFactory.ip` trait. To listen on all interfaces, specify:
714+
:attr:`IPController.ip` trait. To listen on all interfaces, specify:
715715

716716
.. sourcecode:: python
717717

718-
c.HubFactory.ip = '*'
718+
c.IPController.ip = '*'
719719

720720
When connecting to a Controller that is listening on loopback or behind a firewall, it may
721721
be necessary to specify an SSH server to use for tunnels, and the external IP of the
722-
Controller. If you specified that the HubFactory listen on loopback, or all interfaces,
722+
Controller. If you specified that the IPController listen on loopback, or all interfaces,
723723
then IPython will try to guess the external IP. If you are on a system with VM network
724724
devices, or many interfaces, this guess may be incorrect. In these cases, you will want
725725
to specify the 'location' of the Controller. This is the IP of the machine the Controller
@@ -733,22 +733,22 @@ through the login node, an example :file:`ipcontroller_config.py` might contain:
733733
# allow connections on all interfaces from engines
734734
# engines on the same node will use loopback, while engines
735735
# from other nodes will use an external IP
736-
c.HubFactory.ip = '*'
736+
c.IPController.ip = '*'
737737

738738
# you typically only need to specify the location when there are extra
739739
# interfaces that may not be visible to peer nodes (e.g. VM interfaces)
740-
c.HubFactory.location = '10.0.1.5'
740+
c.IPController.location = '10.0.1.5'
741741
# or to get an automatic value, try this:
742742
import socket
743743
hostname = socket.gethostname()
744744
# alternate choices for hostname include `socket.getfqdn()`
745745
# or `socket.gethostname() + '.local'`
746746

747747
ex_ip = socket.gethostbyname_ex(hostname)[-1][-1]
748-
c.HubFactory.location = ex_ip
748+
c.IPController.location = ex_ip
749749

750750
# now instruct clients to use the login node for SSH tunnels:
751-
c.HubFactory.ssh_server = 'login.mycluster.net'
751+
c.IPController.ssh_server = 'login.mycluster.net'
752752

753753
After doing this, your :file:`ipcontroller-client.json` file will look something like this:
754754

@@ -781,23 +781,23 @@ data types.
781781

782782
MongoDB `BSON doc <http://bsonspec.org/>`_
783783

784-
To use one of these backends, you must set the :attr:`HubFactory.db_class` trait:
784+
To use one of these backends, you must set the :attr:`IPController.db_class` trait:
785785

786786
.. sourcecode:: python
787787

788788
# for a simple dict-based in-memory implementation, use dictdb
789789
# This is the default and the fastest, since it doesn't involve the filesystem
790-
c.HubFactory.db_class = 'ipyparallel.controller.dictdb.DictDB'
790+
c.IPController.db_class = 'ipyparallel.controller.dictdb.DictDB'
791791

792792
# To use MongoDB:
793-
c.HubFactory.db_class = 'ipyparallel.controller.mongodb.MongoDB'
793+
c.IPController.db_class = 'ipyparallel.controller.mongodb.MongoDB'
794794

795795
# and SQLite:
796-
c.HubFactory.db_class = 'ipyparallel.controller.sqlitedb.SQLiteDB'
796+
c.IPController.db_class = 'ipyparallel.controller.sqlitedb.SQLiteDB'
797797

798798
# You can use NoDB to disable the database altogether, in case you don't need
799799
# to reuse tasks or results, and want to keep memory consumption under control.
800-
c.HubFactory.db_class = 'ipyparallel.controller.dictdb.NoDB'
800+
c.IPController.db_class = 'ipyparallel.controller.dictdb.NoDB'
801801

802802
When using the proper databases, you can allow for tasks to persist from
803803
one session to the next by specifying the MongoDB database or SQLite table in
@@ -868,9 +868,9 @@ Engine:
868868

869869
.. sourcecode:: python
870870

871-
c.IPEngineApp.startup_script = u'/path/to/my/startup.py'
871+
c.IPEngine.startup_script = u'/path/to/my/startup.py'
872872

873-
c.IPEngineApp.startup_command = 'import numpy, scipy, mpi4py'
873+
c.IPEngine.startup_command = 'import numpy, scipy, mpi4py'
874874

875875
These commands/files will be run again, after each
876876

@@ -879,7 +879,7 @@ in some scratch directory. This can be set with:
879879

880880
.. sourcecode:: python
881881

882-
c.IPEngineApp.work_dir = u'/path/to/scratch/'
882+
c.IPEngine.work_dir = u'/path/to/scratch/'
883883

884884

885885

ipyparallel/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,22 @@ def bind_kernel(**kwargs):
3434
This function returns immediately.
3535
"""
3636
from ipykernel.kernelapp import IPKernelApp
37-
from ipyparallel.apps.ipengineapp import IPEngineApp
37+
from ipyparallel.engine.app import IPEngine
3838

3939
# first check for IPKernelApp, in which case this should be a no-op
4040
# because there is already a bound kernel
4141
if IPKernelApp.initialized() and isinstance(IPKernelApp._instance, IPKernelApp):
4242
return
4343

44-
if IPEngineApp.initialized():
44+
if IPEngine.initialized():
4545
try:
46-
app = IPEngineApp.instance()
46+
app = IPEngine.instance()
4747
except MultipleInstanceError:
4848
pass
4949
else:
5050
return app.bind_kernel(**kwargs)
5151

52-
raise RuntimeError("bind_kernel be called from an IPEngineApp instance")
52+
raise RuntimeError("bind_kernel be called from an IPEngine instance")
5353

5454

5555
def register_joblib_backend(name='ipyparallel', make_default=False):

ipyparallel/apps/baseapp.py

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,17 @@
77
import re
88
import sys
99

10-
from IPython.core import release
1110
from IPython.core.application import base_aliases as base_ip_aliases
1211
from IPython.core.application import base_flags as base_ip_flags
1312
from IPython.core.application import BaseIPythonApplication
14-
from IPython.core.crashhandler import CrashHandler
1513
from IPython.utils.path import expand_path
1614
from IPython.utils.process import check_pid
1715
from ipython_genutils import py3compat
1816
from ipython_genutils.py3compat import unicode_type
17+
from jupyter_client.session import Session
18+
from tornado.ioloop import IOLoop
1919
from traitlets import Bool
20+
from traitlets import default
2021
from traitlets import Dict
2122
from traitlets import Instance
2223
from traitlets import observe
@@ -35,23 +36,6 @@ class PIDFileError(Exception):
3536
pass
3637

3738

38-
# -----------------------------------------------------------------------------
39-
# Crash handler for this application
40-
# -----------------------------------------------------------------------------
41-
42-
43-
class ParallelCrashHandler(CrashHandler):
44-
"""sys.excepthook for IPython itself, leaves a detailed report on disk."""
45-
46-
def __init__(self, app):
47-
contact_name = release.authors['Min'][0]
48-
contact_email = release.author_email
49-
bug_tracker = 'https://github.com/ipython/ipython/issues'
50-
super(ParallelCrashHandler, self).__init__(
51-
app, contact_name, contact_email, bug_tracker
52-
)
53-
54-
5539
# -----------------------------------------------------------------------------
5640
# Main application
5741
# -----------------------------------------------------------------------------
@@ -88,7 +72,11 @@ class BaseParallelApplication(BaseIPythonApplication):
8872

8973
version = __version__
9074

91-
crash_handler_class = ParallelCrashHandler
75+
_deprecated_classes = None
76+
77+
def init_crash_handler(self):
78+
# disable crash handler from IPython
79+
pass
9280

9381
def _log_level_default(self):
9482
# temporarily override default_log_level to INFO
@@ -140,12 +128,16 @@ def _cluster_id_changed(self, change):
140128
def _config_files_default(self):
141129
return ['ipcontroller_config.py', 'ipengine_config.py', 'ipcluster_config.py']
142130

143-
loop = Instance('tornado.ioloop.IOLoop')
131+
loop = Instance(IOLoop)
144132

145133
def _loop_default(self):
146-
from ipyparallel.util import ioloop
134+
return IOLoop.current()
147135

148-
return ioloop.IOLoop.current()
136+
session = Instance(Session)
137+
138+
@default("session")
139+
def _default_session(self):
140+
return Session(parent=self)
149141

150142
aliases = Dict(base_aliases)
151143
flags = Dict(base_flags)
@@ -154,9 +146,38 @@ def _loop_default(self):
154146
def initialize(self, argv=None):
155147
"""initialize the app"""
156148
super(BaseParallelApplication, self).initialize(argv)
149+
self.init_deprecated_config()
157150
self.to_work_dir()
158151
self.reinit_logging()
159152

153+
def init_deprecated_config(self):
154+
if not self._deprecated_classes:
155+
return
156+
deprecated_config_found = False
157+
new_classname = self.__class__.__name__
158+
for deprecated_classname in self._deprecated_classes:
159+
if deprecated_classname in self.config:
160+
cfg = self.config[deprecated_classname]
161+
new_config = self.config[new_classname]
162+
for key, deprecated_value in list(cfg.items()):
163+
if key in new_config:
164+
new_value = new_config[key]
165+
if new_value != deprecated_value:
166+
self.log.warning(
167+
f"Ignoring c.{deprecated_classname}.{key} = {deprecated_value}, overridden by c.{new_classname}.{key} = {new_value}"
168+
)
169+
else:
170+
self.log.warning(
171+
f"c.{deprecated_classname}.{key} is deprecated in ipyparallel 7, use c.{new_classname}.{key} = {deprecated_value}"
172+
)
173+
new_config[key] = deprecated_value
174+
cfg.pop(key)
175+
deprecated_config_found = True
176+
177+
if deprecated_config_found:
178+
# reload config
179+
self.update_config(self.config)
180+
160181
def to_work_dir(self):
161182
wd = self.work_dir
162183
if unicode_type(wd) != py3compat.getcwd():

ipyparallel/apps/ipclusterapp.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import warnings
2+
3+
warnings.warn(f"{__name__} is deprecated in ipyparallel 7. Use ipyparallel.cluster")
4+
5+
from ipyparallel.cluster.app import IPCluster, main
6+
7+
IPClusterApp = IPCluster
8+
launch_new_instance = main
9+
10+
if __name__ == "__main__":
11+
main()

ipyparallel/apps/ipcontrollerapp.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import warnings
2+
3+
warnings.warn(f"{__name__} is deprecated in ipyparallel 7. Use ipyparallel.controller")
4+
5+
from ipyparallel.controller.app import IPController, main
6+
7+
IPControllerApp = IPController
8+
launch_new_instance = main
9+
10+
if __name__ == "__main__":
11+
main()

ipyparallel/apps/ipengineapp.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import warnings
2+
3+
warnings.warn(f"{__name__} is deprecated in ipyparallel 7. Use ipyparallel.engine")
4+
5+
from ipyparallel.engine.app import IPEngine, main
6+
7+
IPEngineApp = IPEngine
8+
launch_new_instance = main
9+
10+
if __name__ == "__main__":
11+
main()

0 commit comments

Comments
 (0)