natlinkcore 5.4.0__tar.gz → 5.4.2.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/PKG-INFO +50 -8
  2. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/pyproject.toml +6 -4
  3. natlinkcore-5.4.2.dev1/readme.md +81 -0
  4. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/__init__.py +5 -1
  5. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/config.py +15 -16
  6. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/natlinkconfig_gui.py +4 -4
  7. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/loader.py +27 -0
  8. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/natlinkstatus.py +34 -9
  9. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/natlinkutils.py +70 -35
  10. natlinkcore-5.4.0/readme.md +0 -39
  11. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/DefaultConfig/_config_instructions.py +0 -0
  12. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/DefaultConfig/_information_config.py +0 -0
  13. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/DefaultConfig/natlink.ini +0 -0
  14. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/Index.htm +0 -0
  15. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_globals.py +0 -0
  16. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_mouse.py +0 -0
  17. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_repeatthat.py +0 -0
  18. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sample1.py +0 -0
  19. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sample2.py +0 -0
  20. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sample3.py +0 -0
  21. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sample4.py +0 -0
  22. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sample5.py +0 -0
  23. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sample8.py +0 -0
  24. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sample9.py +0 -0
  25. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/_sleeping.py +0 -0
  26. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/excel_sample7.py +0 -0
  27. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/natspeak_sample6.py +0 -0
  28. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/trainuser.py +0 -0
  29. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/transcribe.py +0 -0
  30. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/wiki.css +0 -0
  31. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/windict.py +0 -0
  32. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/winspch.py +0 -0
  33. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/winword_styles_sample.py +0 -0
  34. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/OriginalSampleMacros/wordpad.py +0 -0
  35. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/__init__.py +0 -0
  36. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_debug_natlink.py +0 -0
  37. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_sample7.py +0 -0
  38. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_sample_activatedeactivate.py +0 -0
  39. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_sample_callback.py +0 -0
  40. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_sample_directory_information.py +0 -0
  41. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_sample_move_natlinktimer.py +0 -0
  42. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_sample_natlinkstatus.py +0 -0
  43. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_sample_runmimic.py +0 -0
  44. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/SampleMacros/_samplehypothesis.py +0 -0
  45. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/_natlink_core.pyi +0 -0
  46. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/callbackhandler.py +0 -0
  47. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/README.md +0 -0
  48. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/__init__.py +0 -0
  49. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/foo.txt +0 -0
  50. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/list of functions.txt +0 -0
  51. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/loggert.py +0 -0
  52. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/natlink_extensions.py +0 -0
  53. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/natlinkconfig_cli.py +0 -0
  54. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/configure/natlinkconfigfunctions.py +0 -0
  55. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/gramparser.py +0 -0
  56. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/natlink.pyi +0 -0
  57. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/natlinkpydebug.py +0 -0
  58. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/natlinktimer.py +0 -0
  59. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/nsformat.py +0 -0
  60. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/py.typed +0 -0
  61. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/readwritefile.py +0 -0
  62. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/redirect_output.py +0 -0
  63. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/singleton.py +0 -0
  64. {natlinkcore-5.4.0 → natlinkcore-5.4.2.dev1}/src/natlinkcore/tkinter_dialogs.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: natlinkcore
3
- Version: 5.4.0
3
+ Version: 5.4.2.dev1
4
4
  Summary: Python portion of Natlink, a compatibility module for Dragon Naturally Speaking
5
5
  Author-email: "Quintijn Hoogenboom (maintainer)" <q.hoogenboom@antenna.nl>
6
6
  Requires-Python: >=3.9
@@ -13,11 +13,11 @@ Classifier: Programming Language :: Python :: 3.9
13
13
  Classifier: Programming Language :: Python :: Implementation :: CPython
14
14
  Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
15
15
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
- Requires-Dist: natlink>=5.3.4
17
16
  Requires-Dist: FreeSimpleGUI>=5.1.0
18
17
  Requires-Dist: pydebugstring >= 1.0.0.1
19
- Requires-Dist: dtactions>=1.6.2
18
+ Requires-Dist: dtactions>=1.6.3
20
19
  Requires-Dist: platformdirs >= 4.2.0
20
+ Requires-Dist: natlink ~= 5.5, >= 5.5.7
21
21
  Requires-Dist: pyenvutils ; extra == "dev"
22
22
  Requires-Dist: entry-point-inspector ; extra == "dev"
23
23
  Requires-Dist: build ; extra == "dev"
@@ -55,10 +55,52 @@ Mandy Python IDEs such as [Visual Studio Code](https://code.visualstudio.com/) h
55
55
  Publishing to PyPi is done through the [trusted publisher mechanism](https://docs.pypi.org/trusted-publishers/using-a-publisher/) when a release is created on github using github actions.
56
56
 
57
57
 
58
- ## Publishing checklist
59
- Before you bump the version number in __init__.py and publish:
60
- - Check the pyroject.toml file for package dependancies. Do you need a specfic or newer version of
61
- a dependancy such as dtactions? Then add or update the version # requirement in dtactions.
58
+ ## Version Numbering and Publishing Checklist
59
+
60
+ While you are developing, use a .dev release number. When you are ready for alpha or beta or release candidate, use the appropriate version numbers.
61
+ If you are submitting a pull request, the review should review and adjust the version number.
62
+ The version specificier is in pyroject.toml.
63
+
64
+
65
+ The version number progression is explained in [PEP440](https://peps.python.org/pep-0440/#summary-of-permitted-suffixes-and-relative-ordering).
66
+
67
+ Hypothetical Progression of release numbers.
68
+
69
+ Working towards 5.4.0:
70
+ - 5.4.0.dev1
71
+ - 5.4.0.dev2
72
+ - 5.4.0.dev_feature_x
73
+ - 5.4.0a1
74
+ - 5.4.0b1dev1
75
+ - 5.4.0b1
76
+ - 5.4.0rc1
77
+ - 5.4.0rc2
78
+ - 5.4.0
79
+
80
+ Use alpha and beta specifiers (5.4a2, 5.4.b1, etc) to release alphas and betas.
81
+ If you go through a release candidate phase, use 5.4rc1 etc.
82
+
83
+ Non breaking changes, add a micro version number. ie from version 5.4.1 to 5.4.2.
84
+ Breaking changes, add a minor version number.
85
+
86
+ *Before you publish to pypi*:
87
+ - doublecheck the dependancies, especially on natlink. You may want to specify a minimum natlink (i.e. 5.5.3) and
88
+ normally you should also specify that natlink has not had a breaking change by specifying the major and minor version numbers are as expected. Note that this requires a release of natlinkcore if the minor version of natlink changes. At minimum this will require an update to pyproject.toml and a release to pypi, even if no python code has changed.
89
+
90
+
91
+
92
+ This is how the version specifier should look for natlink (subsituting the version numbers appropriate). In this case, we are saying that any natlink 5.5 is required, and that
93
+ we require greater than 5.5.7 as well because we are relying on a non-breaking change introduced in 5.5.7.
94
+ ` "natlink ~= 5.5, >= 5.5.7"
95
+ `
96
+ Often, the natlink dependancy should just specify the major and minor version:
97
+ `
98
+ "natlink ~= 5.5"
99
+ `
100
+
101
+ You could have a case where natlinkcore works with natlink 5.5 and 5.6, you could express this in pyproject.toml as
102
+ "natlink ~= 5.5, ~= 5.6".
103
+
62
104
 
63
105
  ## Debugging Instructions
64
106
 
@@ -5,15 +5,17 @@ build-backend = "flit_core.buildapi"
5
5
  [project]
6
6
  name = "natlinkcore"
7
7
  authors = [{name = "Quintijn Hoogenboom (maintainer)", email = "q.hoogenboom@antenna.nl"}]
8
- dynamic = ["version", "description"]
8
+ version="5.4.2.dev1"
9
+ dynamic = [ "description"]
9
10
  requires-python = ">=3.9"
10
11
  readme = "readme.md"
11
12
  dependencies= [
12
- "natlink>=5.3.4",
13
+
13
14
  "FreeSimpleGUI>=5.1.0",
14
15
  "pydebugstring >= 1.0.0.1",
15
- "dtactions>=1.6.2",
16
- "platformdirs >= 4.2.0"
16
+ "dtactions>=1.6.3",
17
+ "platformdirs >= 4.2.0",
18
+ "natlink ~= 5.5, >= 5.5.7"
17
19
  ]
18
20
  classifiers=[
19
21
  "Development Status :: 4 - Beta",
@@ -0,0 +1,81 @@
1
+
2
+ # Natlinkcore
3
+
4
+ ## More Information
5
+ Please refer to the README file in the project repository [https://github.com/dictation-toolbox/natlink](https://github.com/dictation-toolbox/natlink) for more information about natlink.
6
+
7
+ ## Installing from PyPi
8
+ You can install from [The Python Package Index (PyPI)](https://pypi.org/) with
9
+
10
+ `py -m pip install natlinkcore`
11
+
12
+ Note that natlinkcore will not install if you have not installed Natlink first. Natlink is installed through running an installer.
13
+
14
+
15
+ ## Test Framework
16
+ Tests use the [pytest](https://docs.pytest.org/) framework.
17
+ For developers, if you are developing on the project, please add tests for any new features or bug
18
+ fixes.
19
+
20
+ Mandy Python IDEs such as [Visual Studio Code](https://code.visualstudio.com/) have build in support for test frameworks and make it easy to run and debug pytest. see [Visual Studio Code for testing](https://code.visualstudio.com/docs/python/testing).
21
+
22
+
23
+ ## Building the Python Package Locally
24
+
25
+ `py -m build` to build the Python package locally.
26
+
27
+ Publishing to PyPi is done through the [trusted publisher mechanism](https://docs.pypi.org/trusted-publishers/using-a-publisher/) when a release is created on github using github actions.
28
+
29
+
30
+ ## Version Numbering and Publishing Checklist
31
+
32
+ While you are developing, use a .dev release number. When you are ready for alpha or beta or release candidate, use the appropriate version numbers.
33
+ If you are submitting a pull request, the review should review and adjust the version number.
34
+ The version specificier is in pyroject.toml.
35
+
36
+
37
+ The version number progression is explained in [PEP440](https://peps.python.org/pep-0440/#summary-of-permitted-suffixes-and-relative-ordering).
38
+
39
+ Hypothetical Progression of release numbers.
40
+
41
+ Working towards 5.4.0:
42
+ - 5.4.0.dev1
43
+ - 5.4.0.dev2
44
+ - 5.4.0.dev_feature_x
45
+ - 5.4.0a1
46
+ - 5.4.0b1dev1
47
+ - 5.4.0b1
48
+ - 5.4.0rc1
49
+ - 5.4.0rc2
50
+ - 5.4.0
51
+
52
+ Use alpha and beta specifiers (5.4a2, 5.4.b1, etc) to release alphas and betas.
53
+ If you go through a release candidate phase, use 5.4rc1 etc.
54
+
55
+ Non breaking changes, add a micro version number. ie from version 5.4.1 to 5.4.2.
56
+ Breaking changes, add a minor version number.
57
+
58
+ *Before you publish to pypi*:
59
+ - doublecheck the dependancies, especially on natlink. You may want to specify a minimum natlink (i.e. 5.5.3) and
60
+ normally you should also specify that natlink has not had a breaking change by specifying the major and minor version numbers are as expected. Note that this requires a release of natlinkcore if the minor version of natlink changes. At minimum this will require an update to pyproject.toml and a release to pypi, even if no python code has changed.
61
+
62
+
63
+
64
+ This is how the version specifier should look for natlink (subsituting the version numbers appropriate). In this case, we are saying that any natlink 5.5 is required, and that
65
+ we require greater than 5.5.7 as well because we are relying on a non-breaking change introduced in 5.5.7.
66
+ ` "natlink ~= 5.5, >= 5.5.7"
67
+ `
68
+ Often, the natlink dependancy should just specify the major and minor version:
69
+ `
70
+ "natlink ~= 5.5"
71
+ `
72
+
73
+ You could have a case where natlinkcore works with natlink 5.5 and 5.6, you could express this in pyproject.toml as
74
+ "natlink ~= 5.5, ~= 5.6".
75
+
76
+
77
+ ## Debugging Instructions
78
+
79
+ Read the detailed developer instructions for setting up the debugger. You can look in this projects tree until
80
+ documentation/developers.rst.
81
+
@@ -1,6 +1,10 @@
1
1
  '''Python portion of Natlink, a compatibility module for Dragon Naturally Speaking
2
2
  The python stuff including test modules'''
3
- __version__="5.4.0"
3
+
4
+ import importlib.metadata
5
+
6
+ __version__ = importlib.metadata.version(__package__) #version set in pyproject.toml now.
7
+
4
8
  #pylint:disable=
5
9
  from pathlib import Path
6
10
 
@@ -1,4 +1,4 @@
1
- #pylint:disable=C0114, C0115, C0116, R0913, E1101, R0911, R0914, W0702
1
+ #pylint:disable=C0114, C0115, C0116, R0913, E1101, R0911, R0914, W0702, R0912, C0209
2
2
  import sys
3
3
  import configparser
4
4
  import logging
@@ -144,20 +144,19 @@ class NatlinkConfig:
144
144
  raise NoGoodConfigFoundException('No natlink config file found, please run configure natlink program\n\t(***configurenatlink***)')
145
145
 
146
146
  def expand_path(input_path: str) -> str:
147
- r"""expand path if it starts with "~" or has environment variables (%XXXX%)
147
+ r"""expand path if it starts with "~" or starts with an environment variable or name of python package
148
148
 
149
- Paths can be:
150
-
151
- - the name of a python package, or a sub directory of a python package
152
- - Obsolete: natlink_userdir/...: the directory where natlink.ini is is searched for, either %(NATLINK_USERDIR) or ~/.natlink
153
- - ~/...: the home directory
154
- - Now: natlink_settingsdir/...: the directory where natlink.ini is is searched for, either %(NATLINK_SETTINGSDIR) or ~/.natlink
155
- - ~/...: the home directory
156
- - some environment variable: this environment variable is expanded.
157
-
158
- The Documents directory can be found by "~\Documents"...
159
-
160
- When nothing to expand, return input
149
+ Paths can be:
150
+
151
+ - the name of a python package, or a sub directory of a python package
152
+ - natlink_settingsdir/...: the directory where natlink.ini is is searched for, either`%(NATLINK_SETTINGSDIR)` or `~/.natlink`
153
+ - `~/...`: the home directory
154
+ - Obsolete: natlink_userdir/...: instead natlink_settingsdir will be searched for, and a message is thrown. In the config program things are checked more thoroughly.
155
+ - some other environment variable: this environment variable is expanded
156
+
157
+ The Documents directory can be found by "~\Documents"...
158
+
159
+ When there is nothing to expand, just return the input
161
160
  """
162
161
  expanduser, expandvars, normpath, isdir = os.path.expanduser, os.path.expandvars, os.path.normpath, os.path.isdir
163
162
 
@@ -228,10 +227,10 @@ def expand_path(input_path: str) -> str:
228
227
  return normpath(env_expanded)
229
228
 
230
229
  def expand_natlink_settingsdir():
231
- """not with envvariables, but special:
230
+ """Return the location of the natlink config files
232
231
 
233
232
  if NATLINK_SETTINGSDIR is set: return this, but... it should end with ".natlink"
234
- if NATLINK_SETTINGSDIR is NOT set: return Path.home()/'.natlink'
233
+ if NATLINK_SETTINGSDIR is NOT set: return `Path.home()/'.natlink'`
235
234
  """
236
235
  normpath = os.path.normpath
237
236
  nsd = os.getenv('natlink_settingsdir')
@@ -56,14 +56,14 @@ def collapse(layout, key, visible):
56
56
 
57
57
  #### Hidden UI Columns ####
58
58
  dragonfly2_section = [[sg.Text('Dragonfly', text_color='black')],
59
- [sg.T('Dragonfly user directory:', tooltip='The directory to dragonfly2 user scripts (UserDirectory can also be used)'), sg.Input(Status.getDragonflyUserDirectory(), key='Set_UserDir_Dragonfly2', enable_events=True, readonly=True), sg.FolderBrowse(), sg.B("Clear", key='Clear_UserDir_Dragonfly2', enable_events=True)]]
59
+ [sg.T('Dragonfly user directory:', tooltip='The directory to dragonfly2 user scripts (UserDirectory can also be used)'), sg.Input(Status.getDragonflyUserDirectory(), key='Set_UserDir_Dragonfly2', enable_events=False, readonly=False), sg.FolderBrowse(), sg.B("Clear", key='Clear_UserDir_Dragonfly2', enable_events=True)]]
60
60
 
61
61
  unimacro_section = [[sg.T('Unimacro', text_color='black')],
62
- [sg.T('Unimacro user directory:', tooltip=r'Where the Unimacro user INI files are located, and several other directories (~ or %HOME% allowed)'), sg.I(Status.getUnimacroUserDirectory(), key='Set_UserDir_Unimacro', enable_events=True, readonly=True), sg.FolderBrowse(), sg.B("Clear", key='Clear_UserDir_Unimacro', enable_events=True)]]
62
+ [sg.T('Unimacro user directory:', tooltip=r'Where the Unimacro user INI files are located, and several other directories (~ or %HOME% allowed)'), sg.I(Status.getUnimacroUserDirectory(), key='Set_UserDir_Unimacro', enable_events=False, readonly=False), sg.FolderBrowse(), sg.B("Clear", key='Clear_UserDir_Unimacro', enable_events=True)]]
63
63
 
64
64
  extras_section = [[sg.T('Natlink Loglevel:'), sg.Combo(default_value=Status.getLogging(), values=("Critical", "Fatal", "Error", "Warning", "Info" , "Debug"), key='Set_Logging_Natlink', enable_events=True, auto_size_text=True, readonly=True)],
65
- [sg.T('Autohotkey exe dir:'), sg.I(Status.getAhkExeDir(), key='Set_Exe_Ahk', enable_events=True, readonly=True), sg.FolderBrowse(), sg.B("Clear", key='Clear_Exe_Ahk', enable_events=True)],
66
- [sg.T('Autohotkey scripts dir:'), sg.I(Status.getAhkUserDir(), key='Set_ScriptsDir_Ahk', enable_events=True, readonly=True), sg.FolderBrowse(), sg.B("Clear", key='Clear_ScriptsDir_Ahk', enable_events=True)],
65
+ [sg.T('Autohotkey exe dir:'), sg.I(Status.getAhkExeDir(), key='Set_Exe_Ahk', enable_events=False, readonly=False), sg.FolderBrowse(), sg.B("Clear", key='Clear_Exe_Ahk', enable_events=False)],
66
+ [sg.T('Autohotkey scripts dir:'), sg.I(Status.getAhkUserDir(), key='Set_ScriptsDir_Ahk', enable_events=False, readonly=False), sg.FolderBrowse(), sg.B("Clear", key='Clear_ScriptsDir_Ahk', enable_events=False)],
67
67
  [sg.T('Natlink GUI Output')],
68
68
  [sg.Output(size=(40,10), echo_stdout_stderr=True, expand_x=True, key='-OUTPUT-')]]
69
69
 
@@ -19,6 +19,7 @@ import debugpy
19
19
 
20
20
  import natlink
21
21
  from natlinkcore.config import LogLevel, NatlinkConfig, expand_path
22
+ from natlinkcore.natlinkutils import idd_reload, idd_exit
22
23
  from natlinkcore.readwritefile import ReadWriteFile
23
24
  from natlinkcore.callbackhandler import CallbackHandler
24
25
  from natlinkcore.singleton import Singleton
@@ -257,6 +258,13 @@ class NatlinkMain(metaclass=Singleton):
257
258
  if d_expanded not in sys.path:
258
259
  sys.path.insert(0, d_expanded)
259
260
 
261
+ @staticmethod
262
+ def _del_dirs_from_path(directories: Iterable[str]) -> None:
263
+ for d in directories:
264
+ d_expanded = expand_path(d)
265
+ if d_expanded in sys.path:
266
+ sys.path.remove(d_expanded)
267
+
260
268
  def _call_and_catch_all_exceptions(self, fn: Callable[[], None]) -> None:
261
269
  try:
262
270
  fn()
@@ -455,6 +463,14 @@ class NatlinkMain(metaclass=Singleton):
455
463
  value -= 1
456
464
  self.load_on_begin_utterance = value
457
465
  self.trigger_load()
466
+
467
+ def on_message_window_callback(self, event):
468
+ if event == idd_reload:
469
+ self.trigger_load(force_load=True)
470
+ natlink.setBeginCallback(self.on_begin_callback)
471
+ natlink.setChangeCallback(self.on_change_callback)
472
+ elif event == idd_exit:
473
+ self.finish()
458
474
 
459
475
  def get_user_language(self, DNSuserDirectory):
460
476
  """return the user language (default "enx") from Dragon inifiles
@@ -545,6 +561,17 @@ class NatlinkMain(metaclass=Singleton):
545
561
  self.trigger_load()
546
562
  natlink.setBeginCallback(self.on_begin_callback)
547
563
  natlink.setChangeCallback(self.on_change_callback)
564
+ natlink.setMessageWindow(self.on_message_window_callback)
565
+
566
+ def finish(self) -> None:
567
+ # reverse changes made by start()
568
+ natlink.setMessageWindow(None)
569
+ natlink.setChangeCallback(None)
570
+ natlink.setBeginCallback(None)
571
+ self.unload_all_loaded_modules()
572
+ self._del_dirs_from_path(self.config.directories)
573
+ natlink.active_loader = None
574
+ self.logger.info('Stopping natlink loader')
548
575
 
549
576
  def setup_logger(self) -> None:
550
577
  for handler in list(self.logger.handlers):
@@ -326,9 +326,10 @@ class NatlinkStatus(metaclass=singleton.Singleton):
326
326
  uuDir = self.getUnimacroUserDirectory()
327
327
  if not uuDir:
328
328
  return False
329
- # ugDir = uuDir # only _control self.getUnimacroGrammarsDirectory()
329
+
330
+ # ugDir = self.getUnimacroGrammarsDirectory()
330
331
  # if not (ugDir and isdir(ugDir)):
331
- # print(f'UnimacroGrammarsDirectory ({ugDir}) not present, please create')
332
+ # print(f'UnimacroGrammarsDirectory ({ugDir}) is not present, should be a subdirectory "unimacrogrammars" of {uDir}, please (re)run your pip install unimacro command, of rerun the "Configure Natlink with GUI" or "Configure Natlink with CLI"')
332
333
  # return False
333
334
  return True
334
335
 
@@ -362,6 +363,9 @@ class NatlinkStatus(metaclass=singleton.Singleton):
362
363
  raise OSError(f'getNatlinkIni: not a valid file: "{path}"')
363
364
  return path
364
365
 
366
+ getnatlinkini = getNatlinkIni
367
+
368
+
365
369
  def getNatlink_Settingsdir(self):
366
370
  """get the directory where "natlink.ini" should be stored
367
371
 
@@ -378,6 +382,8 @@ class NatlinkStatus(metaclass=singleton.Singleton):
378
382
 
379
383
  return str(natlink_settings_dir)
380
384
 
385
+ getnatlink_settingsdir = getNatlink_Settingsdir
386
+
381
387
  def getUnimacroUserDirectory(self):
382
388
  isdir, abspath = os.path.isdir, os.path.abspath
383
389
  if self.UnimacroUserDirectory is not None:
@@ -400,7 +406,7 @@ class NatlinkStatus(metaclass=singleton.Singleton):
400
406
 
401
407
  self.UnimacroUserDirectory = ''
402
408
  return ''
403
-
409
+ getunimacrouserdirectory = getUnimacroUserDirectory
404
410
 
405
411
  def getUnimacroDirectory(self):
406
412
  """return the path to the UnimacroDirectory
@@ -419,6 +425,9 @@ class NatlinkStatus(metaclass=singleton.Singleton):
419
425
  self.UnimacroDirectory = unimacro.__path__[-1]
420
426
  return self.UnimacroDirectory
421
427
 
428
+ getunimacrodirectory = getUnimacroDirectory
429
+
430
+
422
431
  def getUnimacroGrammarsDirectory(self):
423
432
  """return the path to the UnimacroGrammarDirectory
424
433
 
@@ -442,6 +451,8 @@ class NatlinkStatus(metaclass=singleton.Singleton):
442
451
  self.UnimacroGrammarsDirectory = um_grammars_dir
443
452
  return um_grammars_dir
444
453
 
454
+ getunimacrogrammarsdirectory = getUnimacroGrammarsDirectory
455
+
445
456
  def getUnimacroDataDirectory(self):
446
457
  """return the path to the directory where grammars can store data.
447
458
 
@@ -451,6 +462,8 @@ class NatlinkStatus(metaclass=singleton.Singleton):
451
462
  """
452
463
  if self.UnimacroDataDirectory is not None:
453
464
  return self.UnimacroDataDirectory
465
+ if not self.unimacroIsEnabled():
466
+ return ''
454
467
 
455
468
  natlink_settings_dir = self.getNatlink_Settingsdir()
456
469
 
@@ -461,16 +474,22 @@ class NatlinkStatus(metaclass=singleton.Singleton):
461
474
  self.UnimacroDataDirectory = um_data_dir
462
475
 
463
476
  return um_data_dir
477
+
478
+ getunimacrodatadirectory = getUnimacroDataDirectory
464
479
 
465
480
  def getNatlinkDirectory(self):
466
481
  """return the path of the NatlinkDirectory, where the _natlink_core.pyd package (C++ code) is
467
482
  """
468
483
  return self.NatlinkDirectory
469
484
 
485
+ getnatlinkdirectory = getNatlinkDirectory
486
+
470
487
  def getNatlinkcoreDirectory(self):
471
488
  """return the path of the natlinkcore package directory, same as thisDir!
472
489
  """
473
490
  return self.NatlinkcoreDirectory
491
+ getnatlinkcoredirectory = getNatlinkcoreDirectory
492
+
474
493
 
475
494
  def getUserDirectory(self):
476
495
  """return the path to the Natlink User directory
@@ -500,7 +519,8 @@ class NatlinkStatus(metaclass=singleton.Singleton):
500
519
  print('invalid path for UserDirectory: "{value}"')
501
520
  self.UserDirectory = ''
502
521
  return ''
503
-
522
+ getuserdirectory = getUserDirectory
523
+
504
524
  def getDragonflyDirectory(self):
505
525
  """return the path to the DragonflyDirectory
506
526
 
@@ -519,7 +539,7 @@ class NatlinkStatus(metaclass=singleton.Singleton):
519
539
 
520
540
  self.DragonflyDirectory = str(Path(dragonfly2.__file__).parent)
521
541
  return self.DragonflyDirectory
522
-
542
+ getdragonflydirectory = getDragonflyDirectory
523
543
 
524
544
 
525
545
  def getDragonflyUserDirectory(self):
@@ -550,7 +570,7 @@ class NatlinkStatus(metaclass=singleton.Singleton):
550
570
  print('invalid path for DragonflyUserDirectory: "{value}"')
551
571
  self.DragonflyUserDirectory = ''
552
572
  return ''
553
-
573
+ getdragonflyuserdirectory = getDragonflyUserDirectory
554
574
 
555
575
  def getVocolaUserDirectory(self):
556
576
 
@@ -576,6 +596,8 @@ class NatlinkStatus(metaclass=singleton.Singleton):
576
596
  print(f'invalid path for VocolaUserDirectory: "{value}" (expanded: "{expanded}")')
577
597
  self.VocolaUserDirectory = ''
578
598
  return ''
599
+ getvocolauserdirectory = getVocolaUserDirectory
600
+
579
601
 
580
602
  def getVocolaDirectory(self):
581
603
  if self.VocolaDirectory is not None:
@@ -588,7 +610,7 @@ class NatlinkStatus(metaclass=singleton.Singleton):
588
610
  return ''
589
611
  self.VocolaDirectory = vocola2.__path__[-1]
590
612
  return self.VocolaDirectory
591
-
613
+ getvocoladirectory = getVocolaDirectory
592
614
 
593
615
  def getVocolaGrammarsDirectory(self):
594
616
  """return the VocolaGrammarsDirectory, but only if Vocola is enabled
@@ -611,6 +633,7 @@ class NatlinkStatus(metaclass=singleton.Singleton):
611
633
  voc_grammars_dir = natlinkcore.config.expand_path(value)
612
634
  self.VocolaGrammarsDirectory = voc_grammars_dir
613
635
  return voc_grammars_dir
636
+ getvocolagrammarsdirectory = getVocolaGrammarsDirectory
614
637
 
615
638
  def getDtactionsDirectory(self):
616
639
  """dtactions directory should be found with an import (like getUnimacroDirectory)
@@ -625,10 +648,12 @@ class NatlinkStatus(metaclass=singleton.Singleton):
625
648
  return ""
626
649
  self.DtactionsDirectory = dtactions.__path__[-1]
627
650
  return self.DtactionsDirectory
651
+ getdtactionsdirectory = getDtactionsDirectory
652
+
628
653
 
629
654
  def getAhkUserDir(self):
630
655
  return self.getAhkUserDirFromIni()
631
-
656
+ getahkuserdir = getAhkUserDir
632
657
 
633
658
  def getAhkUserDirFromIni(self):
634
659
  isdir, abspath = os.path.isdir, os.path.abspath
@@ -655,7 +680,7 @@ class NatlinkStatus(metaclass=singleton.Singleton):
655
680
  if not self.AhkExeDir is None:
656
681
  return self.AhkExeDir
657
682
  return self.getAhkExeDirFromIni()
658
-
683
+ getahkexedir = getAhkExeDir
659
684
 
660
685
  def getAhkExeDirFromIni(self):
661
686
  isdir, abspath = os.path.isdir, os.path.abspath
@@ -6,11 +6,8 @@ Python Macro Language for Dragon NaturallySpeaking
6
6
 
7
7
  This file contains utility classes and functions for grammar files.
8
8
 
9
- Documentation
10
-
11
- This file contains three base classes and some useful constants and
12
- utility functions:
13
-
9
+ Grammar classes
10
+ ===============
14
11
  GrammarBase - base class for all command and control grammars.
15
12
  See documentation below just before the class definition.
16
13
 
@@ -20,18 +17,24 @@ Python Macro Language for Dragon NaturallySpeaking
20
17
  SelectGramBase - base class for all selection grammars.
21
18
  See documentation below just before the class definition.
22
19
 
20
+
21
+ Functions
22
+ ==========
23
+
24
+ among others, see below:
25
+
23
26
  buttonClick( btnName='left',count=1 )
24
27
  This function simulates a button click or button double click. Pass
25
28
  in the button name ('left','right' or 'middle') and the count (1 or
26
29
  2)
27
30
 
31
+
28
32
  matchWindow( moduleInfo, modName, wndText )
29
33
  A utility function which determines whether moduleInfo matches a
30
34
  specified module name and window title. Returns window handle on
31
35
  match and None on mismatch. Note that moduleInfo may be ("","",0)
32
36
  which we should handle cleanly.
33
37
 
34
-
35
38
  """
36
39
  #pylint:disable=C0116, C0209, C0302, R0902, W0702, E1101, W0703, R1735
37
40
  #pylint:disable=W0237 # inconsistent calling sequences for different classes
@@ -121,6 +124,11 @@ dgnwordflag_title_mode = 0x02000000
121
124
  dgnwordflag_space_bar = 0x08000000
122
125
  dgnwordflag_topicadded = 0x40000000
123
126
  dgnwordflag_DNS8newwrdProp = 0x20000000
127
+
128
+ # The following constants define the window message codes which are passed
129
+ # to the message window callback on menu command activation.
130
+ idd_reload = 32768
131
+ idd_exit = 32769
124
132
 
125
133
  ## temporary fix, remove as soon as natlinkmain is more secure QH (Febr 2021)
126
134
 
@@ -179,7 +187,7 @@ def matchWindow(moduleInfo, modName, wndText):
179
187
 
180
188
  Returns window handle on match and None on mismatch.
181
189
 
182
- Note that moduleInfo may be ("","",0) which we should handle cleanly.
190
+ Note that moduleInfo may be `("", "", 0)` which we should handle cleanly.
183
191
  """
184
192
  if len(moduleInfo) < 3 or not moduleInfo[0]:
185
193
  return None
@@ -288,16 +296,33 @@ def getModifierKeyCodes(modifiers):
288
296
  return [modifier_dict[m] for m in modifiers]
289
297
 
290
298
  def playString(keys, hooks=None):
291
- """Deprecated.
299
+ """natlink.playString was deprecated, but is repaired via a python function with version 5.4.0
292
300
 
293
- natlink.playString, but sometimes has a drop or double of the first character it plays on the screen.
301
+ Therefore this function in natlinkutils is obsolete.
294
302
 
295
- dtactions has a sendkeys function, which can replace playSting most of the time...
303
+ `playString` outputs a string of (keyboard) characters, including
304
+ control characters (like `{ctrl+c}` or `{right 3}`)
305
+ to the foreground window.
306
+
307
+ It is implemented via the `sendkeys` function in repository `dtactions`.
308
+
309
+ ::
310
+
311
+ So you can either do:
312
+
296
313
  from dtactions.sendkeys import sendkeys
297
314
  (...)
298
315
  sendkeys('hello world')
316
+
317
+ or:
318
+
319
+ from natlink import playString
320
+ (...)
321
+ playString('hello world again')
322
+
323
+ And forget about `natlinkutils.playString`!!
299
324
  """
300
- raise DeprecationWarning('use natlink.playString or another sendkeys or sendinput function...')
325
+ natlink.playString(keys)
301
326
 
302
327
  #Classes--------------------------------------------------------------------
303
328
 
@@ -630,24 +655,25 @@ And assume that {list} contains the words "good" and "bad".
630
655
 
631
656
  Now if "this big red object is good" is recognized, the following callbacks
632
657
  will be made (in the order indicated).
633
-
634
- (Note: The second parameter to gotResults_XXX and gotResults is the same as
635
- the second parameter to gotResultsInit. The example has been abbreviated
636
- to save space.)
637
-
638
- gotBegin( ??? )
639
- gotResultsObject( 'self', resObj )
640
- gotResultsInit(
641
- ['this','big','red','object','is','good'],
642
- [('this','start'),('big','ruleOne'),('red','RuleTwo'),
643
- ('object','ruleOne'),('is','start'),('good','start')] )
644
- gotResults_start( ['this'], ... )
645
- gotResults_ruleOne( ['big'], ... )
646
- gotResults_ruleTwo( ['red'], ... )
647
- gotResults_ruleOne( ['object'], ... )
648
- gotResults_start( ['is','good'], ... )
649
- gotResults( ['this','big','red','object','is','good'], ... )
650
- """
658
+ """
659
+ #
660
+ # (Note: The second parameter to gotResults_XXX and gotResults is the same as
661
+ # the second parameter to gotResultsInit. The example has been abbreviated
662
+ # to save space.)
663
+ #
664
+ # gotBegin( ??? )
665
+ # gotResultsObject( 'self', resObj )
666
+ # gotResultsInit(
667
+ # ['this','big','red','object','is','good'],
668
+ # [('this','start'),('big','ruleOne'),('red','RuleTwo'),
669
+ # ('object','ruleOne'),('is','start'),('good','start')] )
670
+ # gotResults_start( ['this'], ... )
671
+ # gotResults_ruleOne( ['big'], ... )
672
+ # gotResults_ruleTwo( ['red'], ... )
673
+ # gotResults_ruleOne( ['object'], ... )
674
+ # gotResults_start( ['is','good'], ... )
675
+ # gotResults( ['this','big','red','object','is','good'], ... )
676
+ # """
651
677
 
652
678
  def __init__(self):
653
679
  GramClassBase.__init__(self)
@@ -1139,7 +1165,9 @@ make default select and through words "select" and "through" (lower case)
1139
1165
  Quintijn december 2010
1140
1166
  adapt to throughWords as well, for future enhancement VoiceCode
1141
1167
  Quintijn August, 2009
1168
+
1142
1169
  load( selectWords=['Select'], throughWord='Through', throughWords=None, allResults=0, hypothesis=0 )
1170
+
1143
1171
  selectWords is a list of words or phrases which can introduce a
1144
1172
  comand of this type. For example, you can pass in a list like
1145
1173
  ['Select','Correct','Insert Before','Insert After'] to simulate
@@ -1202,17 +1230,21 @@ results. The following callback functions can be defined:
1202
1230
  gotResults( words, start, end )
1203
1231
  called when results are available for this grammar.
1204
1232
 
1205
- words = list of recognized words; the first word will be one of
1233
+ words = list of recognized words
1234
+ the first word will be one of
1206
1235
  the words or phrases in selectWords (passed in when the grammar
1207
1236
  was created).
1237
+
1208
1238
  start = index into getSelectText of the start of the selection
1239
+
1209
1240
  end = index into getSelectText of the end of the selection
1210
1241
 
1242
+
1211
1243
  gotHypothesis( words )
1212
1244
  only called when the hypothesis flag is set on load, this callback
1213
1245
  contains the partial recognition hypothesis during recognition.
1214
-
1215
-
1246
+
1247
+
1216
1248
  """
1217
1249
  def load( self, selectWords=None, throughWord='through',
1218
1250
  throughWords=None,allResults=0, hypothesis=0 ):
@@ -1269,9 +1301,10 @@ results. The following callback functions can be defined:
1269
1301
  def makeGrammar(self, selectWords, throughWords):
1270
1302
  """make a selection grammar, which is similar to a Microsoft SAPI grammar.
1271
1303
 
1272
- Use the routines in gramparser.py to build the grammar just like with
1304
+ Uses the routines in `gramparser.py` to build the grammar just like with
1273
1305
  command grammars.
1274
- selectWords and throughWords are lists or words
1306
+
1307
+ `selectWords` and `throughWords` are lists or words.
1275
1308
  """
1276
1309
  output = []
1277
1310
  output.append(struct.pack("LL", 10, 0))
@@ -1294,14 +1327,16 @@ results. The following callback functions can be defined:
1294
1327
 
1295
1328
  #---------------------------------------------------------------------------
1296
1329
 
1297
- # Utility subroutine. This returns the base module name from a complete path
1298
1330
 
1299
1331
  def getBaseName(name):
1332
+ """Utility subroutine. This returns the base module name from a complete path
1333
+ """
1300
1334
  return os.path.splitext(os.path.split(name)[1])[0]
1301
1335
 
1302
1336
 
1303
1337
  def convertResults(fullResults):
1304
1338
  """This utility routine converts a fullResults parameter into a dictionary
1339
+ ::
1305
1340
 
1306
1341
  [ ('red','color'), ('flower','object'), ('and','conj'), ('green','color') ]
1307
1342
  Becomes:
@@ -1,39 +0,0 @@
1
-
2
- # Natlinkcore
3
-
4
- ## More Information
5
- Please refer to the README file in the project repository [https://github.com/dictation-toolbox/natlink](https://github.com/dictation-toolbox/natlink) for more information about natlink.
6
-
7
- ## Installing from PyPi
8
- You can install from [The Python Package Index (PyPI)](https://pypi.org/) with
9
-
10
- `py -m pip install natlinkcore`
11
-
12
- Note that natlinkcore will not install if you have not installed Natlink first. Natlink is installed through running an installer.
13
-
14
-
15
- ## Test Framework
16
- Tests use the [pytest](https://docs.pytest.org/) framework.
17
- For developers, if you are developing on the project, please add tests for any new features or bug
18
- fixes.
19
-
20
- Mandy Python IDEs such as [Visual Studio Code](https://code.visualstudio.com/) have build in support for test frameworks and make it easy to run and debug pytest. see [Visual Studio Code for testing](https://code.visualstudio.com/docs/python/testing).
21
-
22
-
23
- ## Building the Python Package Locally
24
-
25
- `py -m build` to build the Python package locally.
26
-
27
- Publishing to PyPi is done through the [trusted publisher mechanism](https://docs.pypi.org/trusted-publishers/using-a-publisher/) when a release is created on github using github actions.
28
-
29
-
30
- ## Publishing checklist
31
- Before you bump the version number in __init__.py and publish:
32
- - Check the pyroject.toml file for package dependancies. Do you need a specfic or newer version of
33
- a dependancy such as dtactions? Then add or update the version # requirement in dtactions.
34
-
35
- ## Debugging Instructions
36
-
37
- Read the detailed developer instructions for setting up the debugger. You can look in this projects tree until
38
- documentation/developers.rst.
39
-