Start tools
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 7.6 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 9.3 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 8.9 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 81 KiB |
|
@ -22,11 +22,10 @@
|
|||
info
|
||||
mri
|
||||
msgbox
|
||||
now
|
||||
question
|
||||
save_log
|
||||
set_app_config
|
||||
today
|
||||
sleep
|
||||
warning
|
||||
|
||||
|
||||
|
@ -37,6 +36,7 @@
|
|||
|
||||
.. autosummary::
|
||||
|
||||
Dates
|
||||
LOServer
|
||||
MBT
|
||||
MessageBoxType
|
||||
|
|
|
@ -22,6 +22,8 @@ You can used **easymacro** with any extension or directly in your macros.
|
|||
:caption: Contents:
|
||||
|
||||
install
|
||||
tools_debug
|
||||
tools
|
||||
api
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,660 @@
|
|||
Tools
|
||||
=====
|
||||
|
||||
Remember, always import library first.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
|
||||
Info from PC
|
||||
------------
|
||||
|
||||
Operate system
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.OS)
|
||||
|
||||
.. image:: _static/images/tools_01.png
|
||||
|
||||
|
||||
Desktop
|
||||
^^^^^^^
|
||||
|
||||
Name desktop, only GNU/Linux
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.DESKTOP)
|
||||
|
||||
.. image:: _static/images/tools_02.png
|
||||
|
||||
|
||||
Name PC
|
||||
^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.PC)
|
||||
|
||||
.. image:: _static/images/tools_03.png
|
||||
|
||||
|
||||
Current user
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.USER)
|
||||
|
||||
.. image:: _static/images/tools_04.png
|
||||
|
||||
|
||||
Is Windows
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.IS_WIN)
|
||||
|
||||
.. image:: _static/images/tools_05.png
|
||||
|
||||
|
||||
Is Mac
|
||||
^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.IS_MAC)
|
||||
|
||||
.. image:: _static/images/tools_05.png
|
||||
|
||||
|
||||
Info from LibO
|
||||
--------------
|
||||
|
||||
Application name
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.NAME)
|
||||
|
||||
.. image:: _static/images/tools_06.png
|
||||
|
||||
|
||||
Version
|
||||
^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.VERSION)
|
||||
|
||||
.. image:: _static/images/tools_07.png
|
||||
|
||||
|
||||
Language
|
||||
^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.LANG)
|
||||
|
||||
.. image:: _static/images/tools_08.png
|
||||
|
||||
|
||||
Language with variant
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox(app.LANGUAGE)
|
||||
|
||||
.. image:: _static/images/tools_09.png
|
||||
|
||||
|
||||
Message Box
|
||||
-----------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.msgbox('Damed World', 'My Macro')
|
||||
|
||||
.. image:: _static/images/tools_10.png
|
||||
|
||||
|
||||
Show warning box
|
||||
----------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message = 'Caution, this action is dangerous'
|
||||
title = 'My App'
|
||||
app.warning(message, title)
|
||||
|
||||
.. image:: _static/images/tools_11.png
|
||||
|
||||
|
||||
Show error box
|
||||
--------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message = 'ERROR: Contact technical support'
|
||||
title = 'My App'
|
||||
app.errorbox(message, title)
|
||||
|
||||
.. image:: _static/images/tools_12.png
|
||||
|
||||
|
||||
Make question
|
||||
-------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message = 'Is easy Python?'
|
||||
title = 'My App'
|
||||
result = app.question(message, title)
|
||||
app.msgbox(result)
|
||||
|
||||
.. image:: _static/images/tools_13.png
|
||||
|
||||
|
||||
InputBox
|
||||
^^^^^^^^
|
||||
|
||||
* Normal data
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message = 'Type your name'
|
||||
default = ''
|
||||
title = 'My App'
|
||||
|
||||
result = app.inputbox(message, default, title)
|
||||
app.msgbox(result)
|
||||
|
||||
* Private data
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
message = 'Type your password'
|
||||
default = ''
|
||||
title = 'My App'
|
||||
echochar = "*"
|
||||
|
||||
result = app.inputbox(message, default, title, echochar)
|
||||
app.msgbox(result)
|
||||
|
||||
|
||||
Date and times
|
||||
--------------
|
||||
|
||||
Get today
|
||||
^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
app.msgbox(d.today)
|
||||
|
||||
.. image:: _static/images/tools_14.png
|
||||
|
||||
|
||||
Get now
|
||||
^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
app.msgbox(d.now)
|
||||
|
||||
.. image:: _static/images/tools_15.png
|
||||
|
||||
|
||||
Get `Unix Time`_
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
app.msgbox(app.d.epoch)
|
||||
|
||||
.. image:: _static/images/tools_16.png
|
||||
|
||||
|
||||
Simple measure time
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
d.start()
|
||||
app.sleep(5)
|
||||
seconds = d.end()
|
||||
app.msgbox(seconds)
|
||||
|
||||
.. image:: _static/images/tools_17.png
|
||||
|
||||
.. image:: _static/images/tools_18.png
|
||||
|
||||
|
||||
Make date
|
||||
^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
date = d.date(1974, 1, 15)
|
||||
app.msgbox(date)
|
||||
|
||||
.. image:: _static/images/tools_19.png
|
||||
|
||||
.. note::
|
||||
|
||||
Start date in Python and Calc is diferent.
|
||||
|
||||
|
||||
String to date
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
See `Python strftime cheatsheet <https://strftime.org/>`_
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
str_date = '1974-01-15'
|
||||
template = '%Y-%m-%d'
|
||||
date = d.str_to_date(str_date, template)
|
||||
app.msgbox(type(date))
|
||||
|
||||
.. image:: _static/images/tools_20.png
|
||||
|
||||
|
|
||||
|
||||
For correct date for Calc.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
str_date = '1974-01-15'
|
||||
template = '%Y-%m-%d'
|
||||
date = d.str_to_date(str_date, template, True)
|
||||
app.msgbox(type(date))
|
||||
|
||||
.. image:: _static/images/tools_21.png
|
||||
|
||||
|
||||
Calc to date
|
||||
^^^^^^^^^^^^
|
||||
|
||||
Get star date in Calc configuration.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
d = app.dates
|
||||
cell_value = 1
|
||||
date = d.calc_to_date(cell_value)
|
||||
app.msgbox(date)
|
||||
|
||||
.. image:: _static/images/tools_22.png
|
||||
|
||||
|
||||
|
||||
Thread
|
||||
^^^^^^
|
||||
|
||||
You can execute any macro in thread
|
||||
|
||||
* Normal execution
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def show_time(seconds):
|
||||
app.sleep(seconds)
|
||||
app.msgbox(app.NAME)
|
||||
return
|
||||
|
||||
def main(args=None):
|
||||
show_time(5)
|
||||
app.msgbox('Finish...')
|
||||
return
|
||||
|
||||
* Run in thread
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@app.run_in_thread
|
||||
def show_time(seconds):
|
||||
app.sleep(seconds)
|
||||
app.msgbox(app.NAME)
|
||||
return
|
||||
|
||||
def main(args=None):
|
||||
show_time(5)
|
||||
app.msgbox('Finish...')
|
||||
return
|
||||
|
||||
|
||||
Dictionary <-> properties
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
args = {
|
||||
'Hidden': True,
|
||||
'Password': 'letmein',
|
||||
}
|
||||
properties = app.dict_to_property(args)
|
||||
|
||||
app.msgbox(properties)
|
||||
|
||||
data = app.data_to_dict(properties)
|
||||
|
||||
app.msgbox(data)
|
||||
|
||||
|
||||
Tuples or lists to dictionary
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
tuple_of_tuples = (
|
||||
('Hidden', True),
|
||||
('Password', 'letmein'),
|
||||
)
|
||||
data = app.data_to_dict(tuple_of_tuples)
|
||||
app.msgbox(data)
|
||||
|
||||
list_of_lists = [
|
||||
['Hidden', True],
|
||||
['Password', 'letmein'],
|
||||
]
|
||||
data = app.data_to_dict(list_of_lists)
|
||||
app.msgbox(data)
|
||||
|
||||
|
||||
Json
|
||||
^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
data = {
|
||||
'Hidden': True,
|
||||
'Password': 'letmein',
|
||||
}
|
||||
|
||||
json = app.json_dumps(data)
|
||||
|
||||
app.msgbox(json)
|
||||
|
||||
data = app.json_loads(json)
|
||||
|
||||
app.msgbox(data)
|
||||
|
||||
|
||||
Call Macros
|
||||
^^^^^^^^^^^
|
||||
|
||||
You can any macro, for default call macros Python.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def show_message():
|
||||
app.msgbox(app.INFO_DEBUG)
|
||||
return
|
||||
|
||||
def main(args=None):
|
||||
args = {
|
||||
'library': 'test',
|
||||
'name': 'show_message',
|
||||
}
|
||||
app.call_macro(args)
|
||||
return
|
||||
|
||||
Of course is better call directly if both macros are the same languaje, but, you can call macro in Basic too.
|
||||
|
||||
.. code-block:: vbnet
|
||||
|
||||
Sub show_message()
|
||||
MsgBox "Basic from Python"
|
||||
End Sub
|
||||
|
||||
Call from Python with.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
args = {
|
||||
'language': 'Basic',
|
||||
'library': 'Standard',
|
||||
'module': 'Module1',
|
||||
'name': 'show_message',
|
||||
}
|
||||
app.call_macro(args)
|
||||
|
||||
Execute macro in other thread
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app.call_macro(args, True)
|
||||
|
||||
|
||||
Call external program
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
app_name = 'gnome-calculator'
|
||||
app.run(app_name)
|
||||
app.msgbox('ok')
|
||||
|
||||
Call command line and capture output
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
args = 'ls -lh ~'
|
||||
result = app.run(args, True)
|
||||
app.debug(result)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
21/06/2021 22:27:22 - DEBUG - total 1.3M
|
||||
drwxr-xr-x 5 mau mau 4.0K Jun 17 13:09 Desktop
|
||||
drwxr-xr-x 6 mau mau 4.0K Jun 15 12:35 Documents
|
||||
drwxr-xr-x 2 mau mau 4.0K Jun 21 20:26 Downloads
|
||||
drwxr-xr-x 2 mau mau 4.0K Jun 21 16:18 Pictures
|
||||
drwxr-xr-x 13 mau mau 4.0K Jun 21 15:34 Projects
|
||||
drwxr-xr-x 2 mau mau 4.0K May 11 18:48 Templates
|
||||
drwxr-xr-x 2 mau mau 4.0K Jun 20 23:27 Videos
|
||||
|
||||
Call command line and capture output line by line.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
args = 'ls -lh /home/mau'
|
||||
for line in app.popen(args):
|
||||
app.debug(line)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
21/06/2021 22:34:42 - DEBUG - total 1.3M
|
||||
21/06/2021 22:34:42 - DEBUG - drwxr-xr-x 5 mau mau 4.0K Jun 17 13:09 Desktop
|
||||
21/06/2021 22:34:42 - DEBUG - drwxr-xr-x 6 mau mau 4.0K Jun 15 12:35 Documents
|
||||
21/06/2021 22:34:42 - DEBUG - drwxr-xr-x 2 mau mau 4.0K Jun 21 20:26 Downloads
|
||||
21/06/2021 22:34:42 - DEBUG - -rw-r----- 1 mau mau 1.3M Jun 14 11:53 out.png
|
||||
21/06/2021 22:34:42 - DEBUG - drwxr-xr-x 2 mau mau 4.0K Jun 21 16:18 Pictures
|
||||
21/06/2021 22:34:42 - DEBUG - drwxr-xr-x 13 mau mau 4.0K Jun 21 15:34 Projects
|
||||
21/06/2021 22:34:42 - DEBUG - drwxr-xr-x 2 mau mau 4.0K May 11 18:48 Templates
|
||||
21/06/2021 22:34:42 - DEBUG - drwxr-xr-x 2 mau mau 4.0K Jun 20 23:27 Videos
|
||||
|
||||
|
||||
Timer
|
||||
^^^^^
|
||||
|
||||
Execute any macro every seconds.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
TIMER_NAME = 'clock'
|
||||
|
||||
def show_time():
|
||||
app.debug(app.now(True))
|
||||
return
|
||||
|
||||
def start_clock():
|
||||
seconds = 1
|
||||
macro = {
|
||||
'library': 'test',
|
||||
'name': 'show_time',
|
||||
}
|
||||
app.start_timer(TIMER_NAME, seconds, macro)
|
||||
return
|
||||
|
||||
def stop_clock():
|
||||
app.stop_timer(TIMER_NAME)
|
||||
return
|
||||
|
||||
def main(args=None):
|
||||
start_clock()
|
||||
return
|
||||
|
||||
Execute `stop_clock` for stop timer.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
21/06/2021 22:43:17 - INFO - Timer started... show_time
|
||||
21/06/2021 22:43:18 - DEBUG - 22:43:18.080315
|
||||
21/06/2021 22:43:19 - DEBUG - 22:43:19.082211
|
||||
...
|
||||
21/06/2021 22:43:46 - DEBUG - 22:43:46.126446
|
||||
21/06/2021 22:43:47 - DEBUG - 22:43:47.128487
|
||||
21/06/2021 22:43:47 - INFO - Timer stopped... show_time
|
||||
|
||||
|
||||
Get digest
|
||||
^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
data = 'LibreOffice with Python'
|
||||
|
||||
digest = app.sha256(data)
|
||||
app.msgbox(digest)
|
||||
|
||||
digest = app.sha512(data)
|
||||
app.msgbox(digest)
|
||||
|
||||
|
||||
Save and get configurations
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can save any data.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
my_app = 'my_extension'
|
||||
data = {
|
||||
'path': '/home/mau/work',
|
||||
'save_data': True,
|
||||
}
|
||||
|
||||
app.set_config('config', data, my_app)
|
||||
|
||||
app.msgbox('Save config')
|
||||
|
||||
data = app.get_config('config', my_app)
|
||||
|
||||
app.msgbox(data)
|
||||
|
||||
|
||||
Render string
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
template = """Hello $name
|
||||
|
||||
I send you this $file_name
|
||||
|
||||
Best regards
|
||||
"""
|
||||
|
||||
data = {'name': 'Ingrid Bergman', 'file_name': 'letter_love.odt'}
|
||||
|
||||
render = app.render(template, data)
|
||||
|
||||
app.msgbox(render)
|
||||
|
||||
|
||||
Encrypt decrypt
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
You need install library `cryptography`_
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
from conf import PASSWORD
|
||||
|
||||
def encrypt_decrypt():
|
||||
|
||||
data = 'My super secret data'
|
||||
token = app.encrypt(data, PASSWORD)
|
||||
app.msgbox(token)
|
||||
|
||||
data = app.decrypt(token, PASSWORD)
|
||||
app.msgbox(data)
|
||||
|
||||
return
|
||||
|
||||
|
||||
Simple url open
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
* Get text data
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
url = 'https://api.ipify.org'
|
||||
data = app.url_open(url)
|
||||
app.msgbox(data)
|
||||
|
||||
* Get json data
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
url = 'https://api.ipify.org?format=json'
|
||||
data = app.url_open(url, get_json=True)
|
||||
app.msgbox(data)
|
||||
|
||||
For more complex case, you can used `requests`_ or `httpx`_
|
||||
|
||||
|
||||
Color
|
||||
^^^^^
|
||||
|
||||
Look colors that you can used in `web colors`_
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
color_name = 'darkblue'
|
||||
color = app.get_color(color_name)
|
||||
app.msgbox(color)
|
||||
|
||||
color_rgb = (125, 200, 10)
|
||||
color = app.get_color(color_rgb)
|
||||
app.msgbox(color)
|
||||
|
||||
color_html = '#008080'
|
||||
color = app.get_color(color_html)
|
||||
app.msgbox(color)
|
||||
|
||||
|
||||
.. _Unix Time: https://en.wikipedia.org/wiki/Unix_time
|
||||
.. _cryptography: https://github.com/pyca/cryptography
|
||||
.. _requests: https://docs.python-requests.org
|
||||
.. _httpx: https://www.python-httpx.org/
|
||||
.. _web colors: https://en.wikipedia.org/wiki/Web_colors
|
|
@ -0,0 +1,189 @@
|
|||
Tools for debug
|
||||
===============
|
||||
|
||||
INFO_DEBUG
|
||||
----------
|
||||
|
||||
Show info debug, show in message box.
|
||||
|
||||
If you have any problem in your code, you can `open issue`_ in this project,
|
||||
always copy the information of **INFO_DEBUG** in your ticket.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def info():
|
||||
app.msgbox(app.INFO_DEBUG)
|
||||
return
|
||||
|
||||
.. image:: _static/images/install_01.png
|
||||
|
||||
|
|
||||
|
||||
Show in shell.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def info():
|
||||
app.debug(app.INFO_DEBUG)
|
||||
return
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
mau@oficina ~> soffice --calc
|
||||
|
||||
25/02/2022 16:44:24 - DEBUG - LibreOffice v7.3 en-US
|
||||
|
||||
Python: 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0]
|
||||
|
||||
Linux-5.16.11-arch1-1-x86_64-with-glibc2.35
|
||||
|
||||
/usr/lib/libreoffice/program
|
||||
/usr/lib/python310.zip
|
||||
/usr/lib/python3.10
|
||||
/usr/lib/python3.10/lib-dynload
|
||||
/home/mau/.local/lib/python3.10/site-packages
|
||||
/usr/lib/python3.10/site-packages
|
||||
/usr/lib/libreoffice/program/
|
||||
/home/mau/.config/libreoffice/4/user/Scripts/python/pythonpath
|
||||
|
||||
|
||||
Log error
|
||||
---------
|
||||
|
||||
Show message error in shell.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def test_error():
|
||||
msg = 'My error 500'
|
||||
app.error(msg)
|
||||
return
|
||||
|
||||
.. image:: _static/images/toolsdebug_01.png
|
||||
|
||||
|
||||
Log debug
|
||||
---------
|
||||
|
||||
Show message debug in shell.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def test_debug():
|
||||
msg = 'Verify this data...'
|
||||
app.debug(msg)
|
||||
return
|
||||
|
||||
.. image:: _static/images/toolsdebug_02.png
|
||||
|
||||
|
||||
Log info
|
||||
--------
|
||||
|
||||
Show message info in shell.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def test_info():
|
||||
msg = 'Start process...'
|
||||
app.info(msg)
|
||||
return
|
||||
|
||||
.. image:: _static/images/toolsdebug_03.png
|
||||
|
||||
|
||||
Log to file
|
||||
-----------
|
||||
|
||||
Save log to file, automatic add date and time.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def log():
|
||||
app.save_log('/home/mau/log.txt', 'PyUNO')
|
||||
app.save_log('/home/mau/log.txt', 'Damed World')
|
||||
return
|
||||
|
||||
.. image:: _static/images/toolsdebug_04.png
|
||||
|
||||
|
||||
Message Box
|
||||
-----------
|
||||
|
||||
Show any data in message box
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def message():
|
||||
|
||||
msg = 'Please, save the planet'
|
||||
app.msgbox(msg)
|
||||
|
||||
msg = ('one', 2, 'three')
|
||||
app.msgbox(msg)
|
||||
|
||||
msg = {'name': 'Teresa'}
|
||||
app.msgbox(msg)
|
||||
|
||||
app.msgbox(app)
|
||||
|
||||
return
|
||||
|
||||
.. image:: _static/images/toolsdebug_05.png
|
||||
|
||||
|
||||
Catch exceptions
|
||||
----------------
|
||||
|
||||
Sometimes, for difficult errors, you can catch exceptions.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
@app.catch_exception
|
||||
def test():
|
||||
r = 1 / 0
|
||||
return
|
||||
|
||||
.. image:: _static/images/toolsdebug_06.png
|
||||
|
||||
.. warning::
|
||||
|
||||
Not, not used you this function in production.
|
||||
|
||||
|
||||
Call MRI
|
||||
--------
|
||||
|
||||
`MRI`_ is the best extension for debug any object in LibreOffice, you need
|
||||
install before call it.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import easymacro as app
|
||||
|
||||
def error():
|
||||
obj = app.active
|
||||
app.mri(obj)
|
||||
return
|
||||
|
||||
.. image:: _static/images/toolsdebug_07.png
|
||||
|
||||
|
||||
.. _MRI: https://github.com/hanya/MRI
|
||||
.. _open issue: https://git.cuates.net/elmau/easymacro/issues
|
|
@ -69,6 +69,10 @@ SM = CTX.getServiceManager()
|
|||
|
||||
# UNO Enum
|
||||
class MessageBoxType():
|
||||
"""Class for import enum
|
||||
|
||||
`See Api MessageBoxType <https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1awt.html#ad249d76933bdf54c35f4eaf51a5b7965>`_
|
||||
"""
|
||||
from com.sun.star.awt.MessageBoxType \
|
||||
import MESSAGEBOX, INFOBOX, WARNINGBOX, ERRORBOX, QUERYBOX
|
||||
MBT = MessageBoxType
|
||||
|
@ -178,6 +182,17 @@ def get_app_config(node_name: str, key: str='') -> Any:
|
|||
|
||||
|
||||
def set_app_config(node_name: str, key: str, new_value: Any) -> Any:
|
||||
"""Update value for key in node name.
|
||||
|
||||
:param node_name: Name of node
|
||||
:type name: str
|
||||
:param key: Name of key
|
||||
:type key: str
|
||||
:return: True if update sucesfully
|
||||
:rtype: bool
|
||||
|
||||
`See Api ConfigurationUpdateAccess <https://api.libreoffice.org/docs/idl/ref/servicecom_1_1sun_1_1star_1_1configuration_1_1ConfigurationUpdateAccess.html>`_
|
||||
"""
|
||||
result = True
|
||||
current_value = ''
|
||||
name = 'com.sun.star.configuration.ConfigurationProvider'
|
||||
|
@ -210,24 +225,46 @@ def _set_app_command(command: str, disable: bool):
|
|||
node = PropertyValue(Name='nodepath', Value=node_name)
|
||||
update = cp.createInstanceWithArguments(service, (node,))
|
||||
|
||||
if disable:
|
||||
new_node = update.createInstanceWithArguments(())
|
||||
new_node.setPropertyValue('Command', command)
|
||||
update.insertByName(NEW_NODE_NAME, new_node)
|
||||
else:
|
||||
update.removeByName(NEW_NODE_NAME)
|
||||
update.commitChanges()
|
||||
result = True
|
||||
try:
|
||||
if disable:
|
||||
new_node = update.createInstanceWithArguments(())
|
||||
new_node.setPropertyValue('Command', command)
|
||||
update.insertByName(NEW_NODE_NAME, new_node)
|
||||
else:
|
||||
update.removeByName(NEW_NODE_NAME)
|
||||
update.commitChanges()
|
||||
except Exception as e:
|
||||
result = False
|
||||
|
||||
return
|
||||
return result
|
||||
|
||||
|
||||
class commands():
|
||||
# ~ https://wiki.documentfoundation.org/Development/DispatchCommands
|
||||
"""Class for disable and enable commands
|
||||
|
||||
:param command: UNO Command for disable or enable
|
||||
:type command: str
|
||||
|
||||
`See DispatchCommands <https://wiki.documentfoundation.org/Development/DispatchCommands>`_
|
||||
"""
|
||||
def __init__(self, command):
|
||||
self._command = command
|
||||
|
||||
def disable(self):
|
||||
"""Disable command
|
||||
|
||||
:return: True if correctly disable, False if not.
|
||||
:rtype: bool
|
||||
"""
|
||||
return _set_app_command(self._command, True)
|
||||
|
||||
def enabled(self):
|
||||
"""Enable command
|
||||
|
||||
:return: True if correctly enable, False if not.
|
||||
:rtype: bool
|
||||
"""
|
||||
return _set_app_command(self._command, False)
|
||||
|
||||
|
||||
|
@ -239,6 +276,7 @@ LANG = LANGUAGE.split('-')[0]
|
|||
|
||||
INFO_DEBUG = f"{NAME} v{VERSION} {LANGUAGE}\n\n{_info_debug}"
|
||||
|
||||
# Get start date from Calc configuration
|
||||
node = '/org.openoffice.Office.Calc/Calculate/Other/Date'
|
||||
year = get_app_config(node, 'YY')
|
||||
month = get_app_config(node, 'MM')
|
||||
|
@ -287,7 +325,7 @@ def catch_exception(f):
|
|||
|
||||
|
||||
def msgbox(message: Any, title: str=TITLE, buttons=MSG_BUTTONS.BUTTONS_OK, \
|
||||
type_message_box=MessageBoxType.INFOBOX) -> Any:
|
||||
type_message_box=MessageBoxType.INFOBOX) -> int:
|
||||
"""Create message box
|
||||
|
||||
:param message: Any type message, all is converted to string.
|
||||
|
@ -298,8 +336,8 @@ def msgbox(message: Any, title: str=TITLE, buttons=MSG_BUTTONS.BUTTONS_OK, \
|
|||
:type buttons: long
|
||||
:param type_message_box: The `message box type <https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1awt.html#ad249d76933bdf54c35f4eaf51a5b7965>`_
|
||||
:type type_message_box: enum
|
||||
:return: Instance MessageBox
|
||||
:rtype: pyUno
|
||||
:return: `MessageBoxResult <https://api.libreoffice.org/docs/idl/ref/namespacecom_1_1sun_1_1star_1_1awt_1_1MessageBoxResults.html>`_
|
||||
:rtype: int
|
||||
|
||||
`See Api XMessageBoxFactory <http://api.libreoffice.org/docs/idl/ref/interfacecom_1_1sun_1_1star_1_1awt_1_1XMessageBoxFactory.html>`_
|
||||
"""
|
||||
|
@ -310,7 +348,7 @@ def msgbox(message: Any, title: str=TITLE, buttons=MSG_BUTTONS.BUTTONS_OK, \
|
|||
return box.execute()
|
||||
|
||||
|
||||
def question(message: str, title: str=TITLE) -> Any:
|
||||
def question(message: str, title: str=TITLE) -> bool:
|
||||
"""Create message box question, show buttons YES and NO
|
||||
|
||||
:param message: Message question
|
||||
|
@ -325,53 +363,178 @@ def question(message: str, title: str=TITLE) -> Any:
|
|||
return result == YES
|
||||
|
||||
|
||||
def warning(message: Any, title: str=TITLE) -> Any:
|
||||
def warning(message: Any, title: str=TITLE) -> int:
|
||||
"""Create message box with icon warning
|
||||
|
||||
:param message: Any type message, all is converted to string.
|
||||
:type message: Any
|
||||
:param title: The title for message box
|
||||
:type title: str
|
||||
:return: Instance MessageBox
|
||||
:rtype: pyUno
|
||||
:return: MessageBoxResult
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
return msgbox(message, title, type_message_box=MessageBoxType.WARNINGBOX)
|
||||
|
||||
|
||||
def errorbox(message: Any, title: str=TITLE) -> Any:
|
||||
def errorbox(message: Any, title: str=TITLE) -> int:
|
||||
"""Create message box with icon error
|
||||
|
||||
:param message: Any type message, all is converted to string.
|
||||
:type message: Any
|
||||
:param title: The title for message box
|
||||
:type title: str
|
||||
:return: Instance MessageBox
|
||||
:rtype: pyUno
|
||||
:return: MessageBoxResult
|
||||
:rtype: int
|
||||
"""
|
||||
|
||||
return msgbox(message, title, type_message_box=MessageBoxType.ERRORBOX)
|
||||
|
||||
|
||||
def now():
|
||||
"""Current local date and time
|
||||
|
||||
:return: Return the current local date and time
|
||||
:rtype: datetime
|
||||
def sleep(seconds):
|
||||
"""Sleep
|
||||
"""
|
||||
return datetime.datetime.now()
|
||||
time.sleep(seconds)
|
||||
return
|
||||
|
||||
|
||||
def today():
|
||||
"""Current local date
|
||||
class _classproperty:
|
||||
def __init__(self, method=None):
|
||||
self.fget = method
|
||||
|
||||
:return: Return the current local date
|
||||
:rtype: date
|
||||
def __get__(self, instance, cls=None):
|
||||
return self.fget(cls)
|
||||
|
||||
def getter(self, method):
|
||||
self.fget = method
|
||||
return self
|
||||
|
||||
|
||||
class Dates(object):
|
||||
"""Class for datetimes
|
||||
"""
|
||||
return datetime.date.today()
|
||||
_start = None
|
||||
|
||||
@_classproperty
|
||||
def now(cls):
|
||||
"""Current local date and time
|
||||
|
||||
:return: Return the current local date and time
|
||||
:rtype: datetime
|
||||
"""
|
||||
return datetime.datetime.now()
|
||||
|
||||
@_classproperty
|
||||
def today(cls):
|
||||
"""Current local date
|
||||
|
||||
:return: Return the current local date
|
||||
:rtype: date
|
||||
"""
|
||||
return datetime.date.today()
|
||||
|
||||
@_classproperty
|
||||
def epoch(cls):
|
||||
"""Get unix time
|
||||
|
||||
:return: Return unix time
|
||||
:rtype: int
|
||||
|
||||
`See Unix Time <https://en.wikipedia.org/wiki/Unix_time>`_
|
||||
"""
|
||||
n = cls.now
|
||||
e = int(time.mktime(n.timetuple()))
|
||||
return e
|
||||
|
||||
@classmethod
|
||||
def date(cls, year, month, day):
|
||||
"""Get date from year, month, day
|
||||
|
||||
:param year: Year of date
|
||||
:type year: int
|
||||
:param month: Month of date
|
||||
:type month: int
|
||||
:param day: Day of day
|
||||
:type day: int
|
||||
:return: Return the date
|
||||
:rtype: date
|
||||
|
||||
`See Python date <https://docs.python.org/3/library/datetime.html#date-objects>`_
|
||||
"""
|
||||
d = datetime.date(year, month, day)
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def str_to_date(cls, str_date, template, to_calc=False):
|
||||
"""Get date from string
|
||||
|
||||
:param str_date: Date in string
|
||||
:type str_date: str
|
||||
:param template: Formato of date string
|
||||
:type template: str
|
||||
:param to_calc: If date is for used in Calc cell
|
||||
:type to_calc: bool
|
||||
:return: Return date or int if used in Calc
|
||||
:rtype: date or int
|
||||
|
||||
`See Python strptime <https://docs.python.org/3/library/datetime.html#datetime.datetime.strptime>`_
|
||||
"""
|
||||
d = datetime.datetime.strptime(str_date, template).date()
|
||||
if to_calc:
|
||||
d = d.toordinal() - DATE_OFFSET
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def calc_to_date(cls, value):
|
||||
"""Get date from calc value
|
||||
|
||||
:param value: Float value from cell
|
||||
:type value: float
|
||||
:return: Return the current local date
|
||||
:rtype: date
|
||||
|
||||
`See Python fromordinal <https://docs.python.org/3/library/datetime.html#datetime.datetime.fromordinal>`_
|
||||
"""
|
||||
d = datetime.date.fromordinal(int(value) + DATE_OFFSET)
|
||||
return d
|
||||
|
||||
@classmethod
|
||||
def start(cls):
|
||||
"""Start counter
|
||||
"""
|
||||
cls._start = cls.now
|
||||
info('Start: ', cls._start)
|
||||
return
|
||||
|
||||
@classmethod
|
||||
def end(cls, get_seconds: bool=True):
|
||||
"""End counter
|
||||
|
||||
:param get_seconds: If return value in total seconds
|
||||
:type get_seconds: bool
|
||||
:return: Return the timedelta or total seconds
|
||||
:rtype: timedelta or int
|
||||
"""
|
||||
e = cls.now
|
||||
td = e - cls._start
|
||||
result = str(td)
|
||||
if get_seconds:
|
||||
result = td.total_seconds()
|
||||
info('End: ', e)
|
||||
return result
|
||||
|
||||
|
||||
def __getattr__(name):
|
||||
classes = {
|
||||
'dates': Dates
|
||||
}
|
||||
if name in classes:
|
||||
return classes[name]
|
||||
|
||||
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
||||
|
||||
|
||||
class LOServer(object):
|
||||
"""Started LibeOffice like server
|
||||
"""
|
||||
HOST = 'localhost'
|
||||
PORT = '8100'
|
||||
ARG = f'socket,host={HOST},port={PORT};urp;StarOffice.ComponentContext'
|
||||
|
@ -427,6 +590,8 @@ class LOServer(object):
|
|||
return
|
||||
|
||||
def stop(self):
|
||||
"""Stop server
|
||||
"""
|
||||
if self._server is None:
|
||||
print('Search pgrep soffice')
|
||||
else:
|
||||
|
@ -434,7 +599,7 @@ class LOServer(object):
|
|||
debug('LibreOffice is stop...')
|
||||
return
|
||||
|
||||
def create_instance(self, name, with_context=True):
|
||||
def _create_instance(self, name, with_context=True):
|
||||
if with_context:
|
||||
instance = self._sm.createInstanceWithContext(name, self._ctx)
|
||||
else:
|
||||
|
|
|
@ -7,6 +7,7 @@ from test_config import *
|
|||
|
||||
|
||||
LIBO_NAME = 'LibreOffice'
|
||||
# ~ @unittest.SkipTest
|
||||
|
||||
|
||||
class BaseTest(unittest.TestCase):
|
||||
|
@ -23,7 +24,6 @@ class BaseTest(unittest.TestCase):
|
|||
msg = f'In method: {self._testMethodName}'
|
||||
app.debug(msg)
|
||||
|
||||
# ~ @unittest.SkipTest
|
||||
def tearDown(self):
|
||||
pass
|
||||
|
||||
|
|