Show More
@@ -19,6 +19,8 b' from __future__ import print_function' | |||||
19 |
|
19 | |||
20 | # stdlib |
|
20 | # stdlib | |
21 | import errno |
|
21 | import errno | |
|
22 | import io | |||
|
23 | import json | |||
22 | import logging |
|
24 | import logging | |
23 | import os |
|
25 | import os | |
24 | import random |
|
26 | import random | |
@@ -72,6 +74,7 b' from .base.handlers import AuthenticatedFileHandler, FileFindHandler' | |||||
72 |
|
74 | |||
73 | from IPython.config.application import catch_config_error, boolean_flag |
|
75 | from IPython.config.application import catch_config_error, boolean_flag | |
74 | from IPython.core.application import BaseIPythonApplication |
|
76 | from IPython.core.application import BaseIPythonApplication | |
|
77 | from IPython.core.profiledir import ProfileDir | |||
75 | from IPython.consoleapp import IPythonConsoleApp |
|
78 | from IPython.consoleapp import IPythonConsoleApp | |
76 | from IPython.kernel import swallow_argv |
|
79 | from IPython.kernel import swallow_argv | |
77 | from IPython.kernel.zmq.session import default_secure |
|
80 | from IPython.kernel.zmq.session import default_secure | |
@@ -499,6 +502,12 b' class NotebookApp(BaseIPythonApplication):' | |||||
499 | "sent by the upstream reverse proxy. Neccesary if the proxy handles SSL") |
|
502 | "sent by the upstream reverse proxy. Neccesary if the proxy handles SSL") | |
500 | ) |
|
503 | ) | |
501 |
|
504 | |||
|
505 | info_file = Unicode() | |||
|
506 | ||||
|
507 | def _info_file_default(self): | |||
|
508 | info_file = "nbserver-%s.json"%os.getpid() | |||
|
509 | return os.path.join(self.profile_dir.security_dir, info_file) | |||
|
510 | ||||
502 | def parse_command_line(self, argv=None): |
|
511 | def parse_command_line(self, argv=None): | |
503 | super(NotebookApp, self).parse_command_line(argv) |
|
512 | super(NotebookApp, self).parse_command_line(argv) | |
504 |
|
513 | |||
@@ -594,6 +603,20 b' class NotebookApp(BaseIPythonApplication):' | |||||
594 | 'no available port could be found.') |
|
603 | 'no available port could be found.') | |
595 | self.exit(1) |
|
604 | self.exit(1) | |
596 |
|
605 | |||
|
606 | @property | |||
|
607 | def display_url(self): | |||
|
608 | ip = self.ip if self.ip else '[all ip addresses on your system]' | |||
|
609 | return self._url(ip) | |||
|
610 | ||||
|
611 | @property | |||
|
612 | def connection_url(self): | |||
|
613 | ip = self.ip if self.ip else localhost() | |||
|
614 | return self._url(ip) | |||
|
615 | ||||
|
616 | def _url(self, ip): | |||
|
617 | proto = 'https' if self.certfile else 'http' | |||
|
618 | return "%s://%s:%i%s" % (proto, ip, self.port, self.base_project_url) | |||
|
619 | ||||
597 | def init_signal(self): |
|
620 | def init_signal(self): | |
598 | if not sys.platform.startswith('win'): |
|
621 | if not sys.platform.startswith('win'): | |
599 | signal.signal(signal.SIGINT, self._handle_sigint) |
|
622 | signal.signal(signal.SIGINT, self._handle_sigint) | |
@@ -667,7 +690,6 b' class NotebookApp(BaseIPythonApplication):' | |||||
667 | self.log.warn("components submodule unclean, you may see 404s on static/components") |
|
690 | self.log.warn("components submodule unclean, you may see 404s on static/components") | |
668 | self.log.warn("run `setup.py submodule` or `git submodule update` to update") |
|
691 | self.log.warn("run `setup.py submodule` or `git submodule update` to update") | |
669 |
|
692 | |||
670 |
|
||||
671 | @catch_config_error |
|
693 | @catch_config_error | |
672 | def initialize(self, argv=None): |
|
694 | def initialize(self, argv=None): | |
673 | super(NotebookApp, self).initialize(argv) |
|
695 | super(NotebookApp, self).initialize(argv) | |
@@ -691,33 +713,56 b' class NotebookApp(BaseIPythonApplication):' | |||||
691 | "Return the current working directory and the server url information" |
|
713 | "Return the current working directory and the server url information" | |
692 | info = self.notebook_manager.info_string() + "\n" |
|
714 | info = self.notebook_manager.info_string() + "\n" | |
693 | info += "%d active kernels \n" % len(self.kernel_manager._kernels) |
|
715 | info += "%d active kernels \n" % len(self.kernel_manager._kernels) | |
694 | return info + "The IPython Notebook is running at: %s" % self._url |
|
716 | return info + "The IPython Notebook is running at: %s" % self.display_url | |
|
717 | ||||
|
718 | def server_info(self): | |||
|
719 | """Return a JSONable dict of information about this server.""" | |||
|
720 | return {'url': self.connection_url, | |||
|
721 | 'hostname': self.ip if self.ip else 'localhost', | |||
|
722 | 'port': self.port, | |||
|
723 | 'secure': bool(self.certfile), | |||
|
724 | 'baseurlpath': self.base_project_url, | |||
|
725 | 'notebookdir': os.path.abspath(self.notebook_manager.notebook_dir), | |||
|
726 | } | |||
|
727 | ||||
|
728 | def write_server_info_file(self): | |||
|
729 | """Write the result of server_info() to the JSON file info_file.""" | |||
|
730 | with io.open(self.info_file, 'w', encoding='utf-8') as f: | |||
|
731 | json.dump(self.server_info(), f) | |||
|
732 | ||||
|
733 | def remove_server_info_file(self): | |||
|
734 | """Remove the nbserver-<pid>.json file created for this server. | |||
|
735 | ||||
|
736 | Ignores the error raised when the file has already been removed. | |||
|
737 | """ | |||
|
738 | try: | |||
|
739 | os.unlink(self.info_file) | |||
|
740 | except OSError as e: | |||
|
741 | if e.errno != errno.ENOENT: | |||
|
742 | raise | |||
695 |
|
743 | |||
696 | def start(self): |
|
744 | def start(self): | |
697 | """ Start the IPython Notebook server app, after initialization |
|
745 | """ Start the IPython Notebook server app, after initialization | |
698 |
|
746 | |||
699 | This method takes no arguments so all configuration and initialization |
|
747 | This method takes no arguments so all configuration and initialization | |
700 | must be done prior to calling this method.""" |
|
748 | must be done prior to calling this method.""" | |
701 | ip = self.ip if self.ip else '[all ip addresses on your system]' |
|
|||
702 | proto = 'https' if self.certfile else 'http' |
|
|||
703 | info = self.log.info |
|
749 | info = self.log.info | |
704 | self._url = "%s://%s:%i%s" % (proto, ip, self.port, |
|
|||
705 | self.base_project_url) |
|
|||
706 | for line in self.notebook_info().split("\n"): |
|
750 | for line in self.notebook_info().split("\n"): | |
707 | info(line) |
|
751 | info(line) | |
708 | info("Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).") |
|
752 | info("Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).") | |
709 |
|
753 | |||
|
754 | self.write_server_info_file() | |||
|
755 | ||||
710 | if self.open_browser or self.file_to_run: |
|
756 | if self.open_browser or self.file_to_run: | |
711 | ip = self.ip or localhost() |
|
|||
712 | try: |
|
757 | try: | |
713 | browser = webbrowser.get(self.browser or None) |
|
758 | browser = webbrowser.get(self.browser or None) | |
714 | except webbrowser.Error as e: |
|
759 | except webbrowser.Error as e: | |
715 | self.log.warn('No web browser found: %s.' % e) |
|
760 | self.log.warn('No web browser found: %s.' % e) | |
716 | browser = None |
|
761 | browser = None | |
717 |
|
762 | |||
718 | nbdir = os.path.abspath(self.notebook_manager.notebook_dir) |
|
|||
719 | f = self.file_to_run |
|
763 | f = self.file_to_run | |
720 | if f: |
|
764 | if f: | |
|
765 | nbdir = os.path.abspath(self.notebook_manager.notebook_dir) | |||
721 | if f.startswith(nbdir): |
|
766 | if f.startswith(nbdir): | |
722 | f = f[len(nbdir):] |
|
767 | f = f[len(nbdir):] | |
723 | else: |
|
768 | else: | |
@@ -732,8 +777,8 b' class NotebookApp(BaseIPythonApplication):' | |||||
732 | else: |
|
777 | else: | |
733 | url = url_path_join('tree', f) |
|
778 | url = url_path_join('tree', f) | |
734 | if browser: |
|
779 | if browser: | |
735 |
b = lambda : browser.open("%s |
|
780 | b = lambda : browser.open("%s%s" % (self.connection_url, url), | |
736 | self.port, self.base_project_url, url), new=2) |
|
781 | new=2) | |
737 | threading.Thread(target=b).start() |
|
782 | threading.Thread(target=b).start() | |
738 | try: |
|
783 | try: | |
739 | ioloop.IOLoop.instance().start() |
|
784 | ioloop.IOLoop.instance().start() | |
@@ -741,7 +786,21 b' class NotebookApp(BaseIPythonApplication):' | |||||
741 | info("Interrupted...") |
|
786 | info("Interrupted...") | |
742 | finally: |
|
787 | finally: | |
743 | self.cleanup_kernels() |
|
788 | self.cleanup_kernels() | |
|
789 | self.remove_server_info_file() | |||
|
790 | ||||
744 |
|
791 | |||
|
792 | def discover_running_servers(profile='default'): | |||
|
793 | """Iterate over the server info files of running notebook servers. | |||
|
794 | ||||
|
795 | Given a profile name, find nbserver-* files in the security directory of | |||
|
796 | that profile, and yield dicts of their information, each one pertaining to | |||
|
797 | a currently running notebook server instance. | |||
|
798 | """ | |||
|
799 | pd = ProfileDir.find_profile_dir_by_name(get_ipython_dir(), name=profile) | |||
|
800 | for file in os.listdir(pd.security_dir): | |||
|
801 | if file.startswith('nbserver-'): | |||
|
802 | with io.open(os.path.join(pd.security_dir, file), encoding='utf-8') as f: | |||
|
803 | yield json.load(f) | |||
745 |
|
804 | |||
746 | #----------------------------------------------------------------------------- |
|
805 | #----------------------------------------------------------------------------- | |
747 | # Main entry point |
|
806 | # Main entry point |
General Comments 0
You need to be logged in to leave comments.
Login now