Override source code `support files` for grammars in user directory.
Currently Caster tracks grammars in the castorvoice\rules. When grammar is copied over to the user directory .caster\rules it overrides imports so that it's loaded from the user directory .caster\rules instead of source code castorvoice\rules.
For instance if you copy the grammar file eclipse.py into the user directory, It will load from the user directory not the source code. Folder structure doesn't matter eclipse.py could be placed anywhere.
However it does not do the same for support files which contain functions. The template follows this standard (AppName_support\CcrName_support). For example eclipse_support.py Even though it's included with the grammar file in the same directory it still loads from source not the user directory.
This will cause a lot of confusion. What users expect to be able to edit both the grammar and support files and have them loaded from when copied to the user directory.
Why not use conditional imports?
try: # Try first loading from user directory
from eclipse_support import ec_con
except ImportError: # load from source code.
from castervoice.rules.apps.editor.eclipse_rules.eclipse_support import ec_con
That does place limitations though. The user cannot rename eclipse_support.py or have it in a different directory without having to change imports.
This limitation isn't too bad as long as users copies the eclipse_rules directory. As long as the files are together this shouldn't be an issue. This is the case for all grammars in apps and ccr folder as they do not import each other.
Where this becomes a significant issue is the core directory. Application and CCR grammars do import various core support_files.
For instance "eclipse2.py" grammar imports alphabet_support.py
from castervoice.rules.core.alphabet_rules import alphabet_support
Conditional imports are too fragile as we don't know where alphabet_support.py could be placed by the user.
Temporarily addressed through conditional imports https://github.com/dictation-toolbox/Caster/commit/205b39a3b143081e2ff5bc11955b6a30219ffcf8 until a more elegant solution is devised. Does not cover edge cases as mentioned above like "eclipse2.py" with alphabet_support.py
Note: this also affects from castervoice.rules.ccr.standard import SymbolSpecs in ccr
There are many of these support files that either the user would want to customize or are a dependency of a file that the user would want to customize. An ideal solution would allow the user to move either a rule file or a support file to the user/rules folder, or any subfolder thereof, and the user file takes precedence over the caster file.
Implementing this would allow the user to either move a _rule folder and make edits or move an individual file and make edits - both would "just work".
One solution @LexiconCode suggested is to have a function get_support that would handle this. This function would look for a file of a specific name (e.g. alphabet_support.py) anywhere in the user folder. If it couldn't find such a file, it would default to the file in the caster folder. Pseudo-code:
def get_support(default_relative_file_path):
default_relative_file_path = os.normalizepath(default_relative_file_path)
# extract the file
file_name = os.path.basename(default_relative_file_path)
if file_exists(file_name, user_folder):
import that file
else
import default_relative_file_path
I'm guessing imports don't work like this where you import inside a function call. But something like this might work.
That might be away without leveraging casters current system to override grammars. I'm actually hoping to tack on get_support to the current system.