| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| from __future__ import with_statement |
| import contextlib |
| import logging |
|
|
|
|
| logger = logging.getLogger(__name__) |
|
|
|
|
| @contextlib.contextmanager |
| def soffice_subprocess(**kwargs): |
| ''' Create an remote instance of soffice ''' |
|
|
| args = [kwargs.get('soffice', 'soffice')] |
|
|
| if 'accept' in kwargs: |
| args.append('--accept=%s' % kwargs['accept']) |
| |
| if kwargs.get('headless', True): |
| args.append('--headless') |
|
|
| if kwargs.get('invisible', True): |
| args.append('--invisible') |
|
|
| if kwargs.get('nologo', True): |
| args.append('--nologo') |
|
|
| if kwargs.get('norestore', True): |
| args.append('--norestore') |
|
|
| if kwargs.get('nodefault', True): |
| args.append('--nodefault') |
|
|
| if kwargs.get('nofirstwizard', True): |
| args.append('--nofirstwizard') |
|
|
| import subprocess |
| p = subprocess.Popen(args) |
| pid = p.pid |
| logger.info('soffice(%s) has been started.', pid) |
| try: |
| yield p |
| finally: |
| import time |
| n = 0 |
| p.poll() |
| while p.returncode is None: |
| n += 1 |
| if n > 3: |
| p.kill() |
| logger.info('trying to kill soffice(%s)', pid) |
| return |
| p.terminate() |
| time.sleep(1) |
| p.poll() |
| logger.info('soffice(%s) has been terminated with exit code %d', |
| pid, p.returncode) |
|
|
|
|
| def connect_remote_context(uno_link, max_tries=10): |
| ''' Connect to the remote soffice instance and get the context. ''' |
|
|
| from unokit.services import css |
| resolver = css.bridge.UnoUrlResolver() |
| uno_url = 'uno:'+uno_link+'StarOffice.ComponentContext' |
| logger.info('uno_url: %s', uno_url) |
| from com.sun.star.connection import NoConnectException |
| while True: |
| max_tries -= 1 |
|
|
| try: |
| return resolver.resolve(uno_url) |
| except NoConnectException, e: |
| if max_tries <= 0: |
| raise |
| logger.info('%s - retrying', type(e).__name__) |
|
|
| import time |
| time.sleep(1) |
| continue |
|
|
|
|
| @contextlib.contextmanager |
| def new_remote_context(pipe='oxt.tool', retry=3, make_current=True, **kwargs): |
| ''' Create a remote soffice instance and get its context |
| |
| :param pipe: connection pipe name |
| :param retry: connect retry count; default True. |
| :param make_current: whether the remote context would be pushed to be |
| current context; default True. |
| :param **kwargs: arguments to soffice_subprocess() |
| :returns: remote context |
| ''' |
| uno_link = 'pipe,name=%s;urp;' % pipe |
|
|
| logger.debug('uno_link: %s', uno_link) |
|
|
| kwargs['accept'] = uno_link |
| while retry >= 0: |
| with soffice_subprocess(**kwargs): |
| import time |
| time.sleep(1) |
| try: |
| context = connect_remote_context(uno_link, max_tries=10) |
| except Exception, e: |
| logger.exception(e) |
| retry -= 1 |
| continue |
|
|
| if make_current: |
| import unokit.contexts |
| unokit.contexts.push(context) |
| try: |
| yield context |
| finally: |
| unokit.contexts.pop() |
| else: |
| yield context |
| return |
|
|
|
|
| class RemoteContextLayer: |
|
|
| @classmethod |
| def setUp(cls): |
| cls.context = new_remote_context() |
| cls.context.__enter__() |
|
|
| @classmethod |
| def tearDown(cls): |
| cls.context.__exit__(None, None, None) |
|
|
|
|