From 22ac697de1f1f525c6bedd883d6ac6c1f85e1c56 Mon Sep 17 00:00:00 2001 From: El Mau Date: Sat, 26 Feb 2022 00:11:41 -0600 Subject: [PATCH] Doc for call macros --- docs/source/generated/easymacro.rst | 5 + docs/source/tools.rst | 34 +++--- source/easymacro.py | 154 ++++++++++++++++++++++++++-- 3 files changed, 175 insertions(+), 18 deletions(-) diff --git a/docs/source/generated/easymacro.rst b/docs/source/generated/easymacro.rst index 764c14a..2c87f10 100644 --- a/docs/source/generated/easymacro.rst +++ b/docs/source/generated/easymacro.rst @@ -15,7 +15,9 @@ catch_exception create_instance + data_to_dict debug + dict_to_property error errorbox get_app_config @@ -23,6 +25,7 @@ mri msgbox question + run_in_thread save_log set_app_config sleep @@ -37,8 +40,10 @@ .. autosummary:: Dates + Json LOServer MBT + Macro MessageBoxType commands diff --git a/docs/source/tools.rst b/docs/source/tools.rst index 2777022..83191d8 100644 --- a/docs/source/tools.rst +++ b/docs/source/tools.rst @@ -303,13 +303,13 @@ Get star date in Calc configuration. .. image:: _static/images/tools_22.png - Thread -^^^^^^ +------ You can execute any macro in thread -* Normal execution +Normal execution +^^^^^^^^^^^^^^^^ .. code-block:: python @@ -323,7 +323,8 @@ You can execute any macro in thread app.msgbox('Finish...') return -* Run in thread +Run in thread +^^^^^^^^^^^^^ .. code-block:: python @@ -339,8 +340,8 @@ You can execute any macro in thread return -Dictionary <-> properties -^^^^^^^^^^^^^^^^^^^^^^^^^ +Dictionary to/from Properties +----------------------------- .. code-block:: python @@ -358,7 +359,7 @@ Dictionary <-> properties Tuples or lists to dictionary -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +----------------------------- .. code-block:: python @@ -378,7 +379,10 @@ Tuples or lists to dictionary Json -^^^^ +---- + +Dumps data +^^^^^^^^^^ .. code-block:: python @@ -387,19 +391,25 @@ Json 'Password': 'letmein', } - json = app.json_dumps(data) + json = app.json.dumps(data) app.msgbox(json) - data = app.json_loads(json) + +Loads data +^^^^^^^^^^ + +.. code-block:: python + + data = app.json.loads(json) app.msgbox(data) Call Macros -^^^^^^^^^^^ +----------- -You can any macro, for default call macros Python. +You can execute any macro, for default call macros Python. .. code-block:: python diff --git a/source/easymacro.py b/source/easymacro.py index 72e2c8d..548be88 100644 --- a/source/easymacro.py +++ b/source/easymacro.py @@ -20,12 +20,14 @@ import datetime import getpass +import json import logging import os import platform import socket import subprocess import sys +import threading import time import traceback @@ -36,7 +38,7 @@ from typing import Any import uno from com.sun.star.awt import MessageBoxButtons as MSG_BUTTONS from com.sun.star.awt.MessageBoxResults import YES -from com.sun.star.beans import PropertyValue +from com.sun.star.beans import PropertyValue, NamedValue LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' @@ -389,13 +391,67 @@ def errorbox(message: Any, title: str=TITLE) -> int: return msgbox(message, title, type_message_box=MessageBoxType.ERRORBOX) -def sleep(seconds): +def sleep(seconds: int): """Sleep """ time.sleep(seconds) return +def run_in_thread(fn): + """Run any function in thread + + :param fn: Any Python function (macro) + :type fn: Function instance + """ + def run(*k, **kw): + t = threading.Thread(target=fn, args=k, kwargs=kw) + t.start() + return t + return run + + +def dict_to_property(values: dict, uno_any: bool=False): + """Convert dictionary to array of PropertyValue + + :param values: Dictionary of values + :type values: dict + :param uno_any: If return like array uno.Any + :type uno_any: bool + :return: Tuple of PropertyValue or array uno.Any + :rtype: tuples or uno.Any + """ + ps = tuple([PropertyValue(Name=n, Value=v) for n, v in values.items()]) + if uno_any: + ps = uno.Any('[]com.sun.star.beans.PropertyValue', ps) + return ps + + +def _property_to_dict(values): + d = {v.Name: v.Value for v in values} + return d + + +def data_to_dict(data) -> dict: + """Convert tuples, list, PropertyValue, NamedValue to dictionary + + :param data: Dictionary of values + :type data: array of tuples, list, PropertyValue or NamedValue + :return: Dictionary + :rtype: dict + """ + d = {} + if not isinstance(data, (tuple, list)): + return d + + if isinstance(data[0], (tuple, list)): + d = {r[0]: r[1] for r in data} + elif isinstance(data[0], (PropertyValue, NamedValue)): + d = _property_to_dict(data) + + return d + + class _classproperty: def __init__(self, method=None): self.fget = method @@ -445,7 +501,7 @@ class Dates(object): return e @classmethod - def date(cls, year, month, day): + def date(cls, year: int, month: int, day: int): """Get date from year, month, day :param year: Year of date @@ -463,7 +519,7 @@ class Dates(object): return d @classmethod - def str_to_date(cls, str_date, template, to_calc=False): + def str_to_date(cls, str_date: str, template: str, to_calc: bool=False): """Get date from string :param str_date: Date in string @@ -483,7 +539,7 @@ class Dates(object): return d @classmethod - def calc_to_date(cls, value): + def calc_to_date(cls, value: float): """Get date from calc value :param value: Float value from cell @@ -522,9 +578,95 @@ class Dates(object): return result +class Json(object): + """Class for json data + """ + + @classmethod + def dumps(cls, data: Any) -> str: + """Dumps + + :param data: Any data + :type data: Any + :return: Return string json + :rtype: str + """ + return json.dumps(data, indent=4, sort_keys=True) + + @classmethod + def loads(cls, data: str) -> Any: + """Loads + + :param data: String data + :type data: str + :return: Return any object + :rtype: Any + """ + return json.loads(data) + + +class Macro(object): + """Class for call macro + + `See Scripting Framework `_ + """ + @classmethod + def call(cls, args: dict, in_thread: bool=False): + """Call any macro + + :param args: Dictionary with macro location + :type args: dict + :param in_thread: If execute in thread + :type in_thread: bool + :return: Return None or result of call macro + :rtype: Any + """ + + result = None + if in_thread: + t = threading.Thread(target=cls._call, args=(args,)) + t.start() + else: + result = cls._call(args) + return result + + @classmethod + def _get_url_script(cls, args: dict): + library = args['library'] + name = args['name'] + language = args.get('language', 'Python') + location = args.get('location', 'user') + module = args.get('module', '.') + + if language == 'Python': + module = '.py$' + elif language == 'Basic': + module = f".{module}." + if location == 'user': + location = 'application' + + url = 'vnd.sun.star.script' + url = f'{url}:{library}{module}{name}?language={language}&location={location}' + return url + + @classmethod + def _call(cls, args: dict): + url = cls._get_url_script(args) + args = args.get('args', ()) + + service = 'com.sun.star.script.provider.MasterScriptProviderFactory' + factory = create_instance(service) + script = factory.createScriptProvider('').getScript(url) + result = script.invoke(args, None, None)[0] + + return result + + def __getattr__(name): classes = { - 'dates': Dates + 'dates': Dates, + 'json': Json, + 'macro': Macro, } if name in classes: return classes[name]