Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dr16efforts, including trying to fix problems with Dragon 16 #73

Merged
merged 8 commits into from
May 1, 2024
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ natlink_extensions = "natlinkcore.configure.natlink_extensions:main"
[project.gui-scripts]
natlinkconfig_gui = "natlinkcore.configure.natlinkconfig_gui:main_gui"

[project.entry-points."dt.loggers"]
natlink ="natlinkcore:logname"

[project.entry-points."natlink.extensions"]
natlink_sample_macros = "natlinkcore.SampleMacros:locateme"

Expand Down
5 changes: 4 additions & 1 deletion src/natlinkcore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ def getThisDir(fileOfModule):
"""get directory of calling module
"""
return Path(fileOfModule).parent

def logname():
""" Returns the name of the logger module, which is simply 'natlink'. An entry point is defined for this in pyproject.toml.
"""
return "natlink"
# warningTexts = []
# def warning(text):
# """print warning only once, if warnings is set!
Expand Down
36 changes: 32 additions & 4 deletions src/natlinkcore/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ def expand_path(input_path: str) -> str:
Paths can be:

- the name of a python package, or a sub directory of a python package
- natlink_userdir/...: the directory where natlink.ini is is searched for, either %(NATLINK_USERDIR) or ~/.natlink
- Obsolete: natlink_userdir/...: the directory where natlink.ini is is searched for, either %(NATLINK_USERDIR) or ~/.natlink
- ~/...: the home directory
- Now: natlink_settingsdir/...: the directory where natlink.ini is is searched for, either %(NATLINK_SETTINGSDIR) or ~/.natlink
- ~/...: the home directory
- some environment variable: this environment variable is expanded.

Expand All @@ -168,8 +170,9 @@ def expand_path(input_path: str) -> str:
# print(f'expand_path: "{input_path}" include "~": expanded: "{env_expanded}"')
return normpath(env_expanded)

## "natlink_userdir" will go obsolete, to be replaced with "natlink_settingsdir" below:
if input_path.startswith('natlink_userdir/') or input_path.startswith('natlink_userdir\\'):
nud = expand_natlink_userdir()
nud = expand_natlink_settingsdir()
if isdir(nud):
dir_path = input_path.replace('natlink_userdir', nud)
dir_path = normpath(dir_path)
Expand All @@ -179,6 +182,18 @@ def expand_path(input_path: str) -> str:
return dir_path
print(f'natlink_userdir does not expand to a valid directory: "{nud}"')
return normpath(nud)

if input_path.startswith('natlink_settingsdir/') or input_path.startswith('natlink_settingsdir\\'):
nsd = expand_natlink_settingsdir()
if isdir(nsd):
dir_path = input_path.replace('natlink_settingsdir', nsd)
dir_path = normpath(dir_path)
if isdir(dir_path):
return dir_path
print(f'no valid directory found with "natlink_settingsdir": "{dir_path}"')
return dir_path
print(f'natlink_settingsdir does not expand to a valid directory: "{nsd}"')
return normpath(nsd)


# try if package:
Expand All @@ -204,7 +219,7 @@ def expand_path(input_path: str) -> str:
# print(f'env_expanded: "{env_expanded}", from envvar: "{input_path}"')
return normpath(env_expanded)

def expand_natlink_userdir():
def expand_natlink_settingsdir():
"""not with envvariables, but special:

if NATLINK_USERDIR is set: return this, but... it should end with ".natlink"
Expand All @@ -214,5 +229,18 @@ def expand_natlink_userdir():
nud = os.getenv('natlink_userdir') or str(Path.home()/'.natlink')
nud = normpath(expand_path(nud))
if not nud.endswith('.natlink'):
raise ValueError(f'expand_natlink_userdir: directory "{nud}" should end with ".natlink"\n\tprobably you did not set the windows environment variable "NATLINK_USERDIR" incorrect, let it end with ".natlink".\n\tNote: if this ".natlink" directory does not exist yet, it will be created there.')
raise ValueError(f'expand_natlink_settingsdir: directory "{nud}" should end with ".natlink"\n\tprobably you did not set the windows environment variable "NATLINK_USERDIR" incorrect, let it end with ".natlink".\n\tNote: if this ".natlink" directory does not exist yet, it will be created there.')
return nud

def expand_natlink_settingsdir():
"""not with envvariables, but special:

if NATLINK_SETTINGsDIR is set: return this, but... it should end with ".natlink"
if NATLINK_SETTINGSDIR is NOT set: return Path.home()/'.natlink'
"""
normpath = os.path.normpath
nsd = os.getenv('natlink_settingsdir') or str(Path.home()/'.natlink')
nsd = normpath(expand_path(nsd))
if not nsd.endswith('.natlink'):
raise ValueError(f'expand_natlink_settingsdir: directory "{nsd}" should end with ".natlink"\n\tprobably you did not set the windows environment variable "NATLINK_SETTINGSDIR" incorrect, let it end with ".natlink".\n\tNote: if this ".natlink" directory does not exist yet, it will be created there.')
return nsd
10 changes: 6 additions & 4 deletions src/natlinkcore/configure/natlinkconfig_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@
import cmd
import os
import os.path
from natlinkcore.configure import extensions_and_folders
from platformdirs import user_log_dir
import logging
from pathlib import Path
from natlinkcore.configure import extensions_and_folders
from natlinkcore.configure import natlinkconfigfunctions
import logging
from platformdirs import user_log_dir


appname="natlink"
logdir = Path(user_log_dir(appname=appname,ensure_exists=True))
logfilename=logdir/f"cli_log.txt"
logfilename=logdir/"cli_log.txt"
file_handler = logging.FileHandler(logfilename)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
Expand Down
45 changes: 35 additions & 10 deletions src/natlinkcore/configure/natlinkconfigfunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Quintijn Hoogenboom, January 2008 (...), August 2022
#

#pylint:disable=C0302, W0702, R0904, C0116, W0613, R0914, R0912, R1732, W1514, W0107
#pylint:disable=C0302, W0702, R0904, C0116, W0613, R0914, R0912, R1732, W1514, W0107, W1203
"""With the functions in this module Natlink can be configured.

These functions are called in different ways:
Expand All @@ -23,15 +23,14 @@
from pprint import pformat
from pathlib import Path
import configparser
import logging

from natlinkcore import natlinkstatus
from natlinkcore import config
from natlinkcore import loader
from natlinkcore import readwritefile
from natlinkcore import tkinter_dialogs

import logging

isfile, isdir, join = os.path.isfile, os.path.isdir, os.path.join


Expand Down Expand Up @@ -66,9 +65,11 @@ def __init__(self):
# for convenience in other places:
self.home_path = str(Path.home())
self.documents_path = str(Path.home()/'Documents')
self.natlinkconfig_path = config.expand_natlink_userdir()
self.natlinkconfig_path = config.expand_natlink_settingsdir()
pass

def get_check_config_locations(self):

"""check the location/locations as given by the loader
"""
config_path, fallback_path = loader.config_locations()
Expand All @@ -84,6 +85,30 @@ def check_config(self):
"""check config_file for possibly unwanted settings
"""
self.config_remove(section='directories', option='default_config')

# change default unimacrogrammarsdirectory:
section = 'directories'
option = 'unimacrogrammarsdirectory'
old_prefix = 'natlink_user'
new_prefix = 'unimacro'
value = self.Config[section][option]
if value and value.find('natlink_user') == 0:
value = value.replace(old_prefix,new_prefix)
self.config_set(section, option, value)
logging.info(f'changed in "natlink.ini", section "directories", unimacro setting "{option}" to value: "{value}"')
pass

if loader.had_msg_error:
logging.error('The environment variable "NATLINK_USERDIR" has been changed to "NATLINK_SETTINGSDIR" by the user, but has a conclicting value')
logging.error('Please remove "NATLINK_USERDIR", in the windows environment variables, dialog User variables, and restart your program')

if loader.had_msg_warning:
logging.error('The key of the environment variable "NATLINK_USERDIR" should be changed to "NATLINK_SETTINGSDIR"')
logging.error('You can do so in "windows environment variables", dialog "User variables". Then your program')


# for key, value in self.Config[section].items():
# print(f'key: {key}, value: {value}')

def getConfig(self):
"""return the config instance
Expand Down Expand Up @@ -309,7 +334,7 @@ def enable_unimacro(self, arg):
unimacro_user_dir = self.config_get('unimacro', 'unimacrouserdirectory')
if not unimacro_user_dir:
return
uniGrammarsDir = r'natlink_userdir\unimacrogrammars'
uniGrammarsDir = r'unimacro\unimacrogrammars'
self.setDirectory('unimacrodirectory','unimacro') #always unimacro

self.setDirectory('unimacrogrammarsdirectory', uniGrammarsDir)
Expand Down Expand Up @@ -420,16 +445,16 @@ def copyUnimacroIncludeFile(self):
toFolder = Path(self.status.getVocolaUserDirectory())
if not unimacroDir.is_dir():
mess = f'copyUnimacroIncludeFile: unimacroDir "{str(unimacroDir)}" is not a directory'
logging.warn(mess)
logging.warning(mess)
return
fromFile = fromFolder/uscFile
if not fromFile.is_file():
mess = f'copyUnimacroIncludeFile: file "{str(fromFile)}" does not exist (is not a valid file)'
logging.warn(mess)
logging.warning(mess)
return
if not toFolder.is_dir():
mess = f'copyUnimacroIncludeFile: vocolaUserDirectory does not exist "{str(toFolder)}" (is not a directory)'
logging.warn(mess)
logging.warning(mess)
return

toFile = toFolder/uscFile
Expand All @@ -445,7 +470,7 @@ def copyUnimacroIncludeFile(self):
logging.info(f'copied "{uscFile}" from "{str(fromFolder)}" to "{str(toFolder)}"')
except:
mess = f'Could not copy new version of "{uscFile}", from "{str(fromFolder)}" to "{str(toFolder)}"'
logging.warn(mess)
logging.warning(mess)
return
return

Expand All @@ -458,7 +483,7 @@ def removeUnimacroIncludeFile(self):
toFolder = Path(self.status.getVocolaUserDirectory())
if not toFolder.is_dir():
mess = f'removeUnimacroIncludeFile: vocolaUserDirectory does not exist "{str(toFolder)}" (is not a directory)'
logging.warn(mess)
logging.warning(mess)
return

toFile = toFolder/uscFile
Expand Down
103 changes: 63 additions & 40 deletions src/natlinkcore/loader.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
#pylint:disable=C0114, C0115, C0116, R1705, R0902, R0904, R0911, R0912, R0915, W0703, E1101
#pylint:disable=C0114, C0115, C0116, R1705, R0902, R0904, R0911, R0912, R0915, W0703, E1101, W1203
import importlib
import importlib.machinery
import importlib.util
import logging
from pydebugstring import outputDebugString,OutputDebugStringHandler
import os
import copy
import sys
import sys
import time
import traceback
import winreg
import configparser
from pathlib import Path
from types import ModuleType
from typing import List, Dict, Set, Iterable, Any, Tuple, Callable
from pydebugstring import outputDebugString,OutputDebugStringHandler
import debugpy

import natlink
Expand Down Expand Up @@ -604,66 +603,90 @@ def get_config_info_from_registry(key_name: str) -> str:
result, _ = winreg.QueryValueEx(natlink_key, key_name)
return result


had_msg_error = False
had_msg_warning = False

def config_locations() -> Iterable[str]:
"""give two possible locations, the wanted and the "fallback" location

wanted: in the '.natlink' subdirectory of `home` or in "NATLINK_USERDIR".
wanted: in the '.natlink' subdirectory of `home` or in "NATLINK_USERDIR", this variable is
going to be replaced by "NATLINK_SETTINGSDIR".
name is always 'natlink.ini'

the fallback location is in the installed files, and provides the frame for the config file.
with the configurenatlink (natlinkconfigfunction.py or configfurenatlink.pyw) the fallback version
of the config file is copied into the wanted location.
"""
global had_msg_warning, had_msg_error
join, expanduser, getenv, isfile = os.path.join, os.path.expanduser, os.getenv, os.path.isfile
home = expanduser('~')
config_sub_dir = '.natlink'
natlink_inifile = 'natlink.ini'
fallback_config_file = join(get_natlinkcore_dirname(), "DefaultConfig", natlink_inifile)
if not isfile(fallback_config_file):
raise OSError(f'fallback_config_file does not exist: "{fallback_config_file}"')
# try NATLINKUSERDIR setting:
natlink_userdir_from_env = getenv("NATLINK_USERDIR")
if natlink_userdir_from_env:
nl_user_dir = expand_path(natlink_userdir_from_env)
nl_user_file = join(nl_user_dir, natlink_inifile)
return [nl_user_file, fallback_config_file]
# try NATLINK_USERDIR setting (obsolete) and NATLINK_SETTINGSDIR (new):
natlink_settingsdir_from_env = getenv("NATLINK_SETTINGSDIR")
natlink_userdir_from_env_obsolete = getenv("NATLINK_USERDIR")
## issue warnings if old setting is still there and conflicts with new setting:
if natlink_userdir_from_env_obsolete:
if natlink_settingsdir_from_env and natlink_userdir_from_env_obsolete:
pass
elif natlink_settingsdir_from_env:
if not had_msg_error:
logging.warning('You defined env variable "NATLINK_SETTINGSDIR", but different from the obsolete env variable "NATLINK_USERDIR"...')
logging.warning('"NATLINK_SETTINGSDIR (valid): "%s"', natlink_settingsdir_from_env)
logging.warning('"NATLINK_USERDIR (obsolete): "%s"', natlink_userdir_from_env_obsolete)
had_msg_error = True
else:
## natlink_settingsdir_from_env is not set, but natlink_userdir_from_env_obsolete IS
if not had_msg_warning:
logging.warning('You have set env variable "NATLINK_USERDIR", but this variable is obsolete.')
logging.warning('Please specify the env variable "NATLINK_SETTINGSDIR" to "%s", and restart Dragon', natlink_userdir_from_env_obsolete)
had_msg_warning = True

if natlink_settingsdir_from_env:
nl_settings_dir = expand_path(natlink_settingsdir_from_env)
nl_settings_file = join(nl_settings_dir, natlink_inifile)
return [nl_settings_file, fallback_config_file]

# choose between .natlink/natlink.ini in home or the fallback_directory:
return [join(home, config_sub_dir, natlink_inifile), fallback_config_file]

def startDap(config : NatlinkConfig) -> bool:
"""
Starts DAP (Debug Adapter Protocol) if there a DAP port specified in the config object.
returns True if the dap was started.
"""
Starts DAP (Debug Adapter Protocol) if there a DAP port specified in the config object.
returns True if the dap was started.

Natlink will startDap automatically if configured in the run method below.
If you need to start the DAP sooner, edit your code to make a call to startDap.
Similarly, if you want to start the DAP later, call startDap. You can call it from your grammar or
anywhere else.
"""
Natlink will startDap automatically if configured in the run method below.
If you need to start the DAP sooner, edit your code to make a call to startDap.
Similarly, if you want to start the DAP later, call startDap. You can call it from your grammar or
anywhere else.
"""

dap_started=False
logging.debug(f"testing dap , enabled {config.dap_enabled} port {config.dap_port}")
try:
logging.debug("Debugpy.configure ...")
debugpy.configure(python=f"{python_exec}")
logging.debug("Debugpy.listen ...")

debugpy.listen(config.dap_port)
dap_started=True

logging.debug(f"DAP Started on Port {config.dap_port} in {__file__}")
if config.dap_wait_for_debugger_attach_on_startup:
#use info level logging, the user will need to know as natlink and dragon will hang here.
#unti debuger is attached.
logging.info(f"waiting for debugger to attach using DAP in {__file__} ")
debugpy.wait_for_client()
return dap_started
except Exception as ee:
logging.info(f"""
Exception {ee} while starting DAP in {__file__}. Possible cause is incorrect python executable specified {python_exec}
""" )
dap_started=False
logging.debug(f"testing dap , enabled {config.dap_enabled} port {config.dap_port}")
try:
logging.debug("Debugpy.configure ...")
debugpy.configure(python=f"{python_exec}")
logging.debug("Debugpy.listen ...")

debugpy.listen(config.dap_port)
dap_started=True

logging.debug(f"DAP Started on Port {config.dap_port} in {__file__}")
if config.dap_wait_for_debugger_attach_on_startup:
#use info level logging, the user will need to know as natlink and dragon will hang here.
#unti debuger is attached.
logging.info(f"waiting for debugger to attach using DAP in {__file__} ")
debugpy.wait_for_client()
return dap_started

except Exception as ee:
logging.info(f"""
Exception {ee} while starting DAP in {__file__}. Possible cause is incorrect python executable specified {python_exec}
""" )


def run() -> None:
Expand Down
1 change: 1 addition & 0 deletions src/natlinkcore/natlinkstatus.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ def getVocolaGrammarsDirectory(self):
key = 'vocolagrammarsdirectory'
value = self.natlinkmain.getconfigsetting(section='directories', option=key)
if not value:
self.VocolaGrammarsDirectory = ""
return ""
voc_grammars_dir = natlinkcore.config.expand_path(value)
self.VocolaGrammarsDirectory = voc_grammars_dir
Expand Down
Loading