| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | 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) |
| |
|
| |
|