[superseded] RcFile: _read: try taskrc directory when trying to load includes - #151
[superseded] RcFile: _read: try taskrc directory when trying to load includes#151smemsh wants to merge 1 commit into
Conversation
smemsh
commented
Oct 10, 2021
@ralphbean could we merge this trivial patch, so relative includes work in taskrc? |
8fe01a9 to
fa9362bComparefa9362b to
49a12f9Comparesmemsh
commented
May 7, 2022
rebased for 1.3.1, looks like @coddingtonbear is the one to merge these? |
coddingtonbear
commented
May 12, 2022
Can, theoretically, but it's going to take some time before I can reasonably have a look at this. |
Taskwarrior itself tries includes as absolute path, then cwd, then relative to rcfile, then in various search paths (see GothenburgBitFactory/libshared -> src/Configuration.cpp -> Configuration::parse()). We won't try to duplicate that whole arrangement here, but at least look relative to the rcfile in addition to cwd/absolute, like taskwarrior does. This will allow specification as relative path in most cases. Otherwise, we'd have to chdir anyways because includes are always tried as-is by taskw. They would only work if specified as absolute paths or if in cwd We use a TaskRc() class variable to store the rcdir because there could be an include chain and all the instances will need to know the same one, but will be processing different paths, so we have to capture the directory of the first one processed, ie the base rcfile. Fixesralphbean#150
49a12f9 to
6ca637eCompareryaminal
commented
Jun 5, 2023
Hi all. Wondering if this fix is still up to date or if there is another solution? seeing this problem emerge from |
RaitoBezarius
commented
Nov 6, 2023
Hi there, @coddingtonbear is there something we can do to help you review this change? It is a very sharp edge currently with |
RaitoBezarius
commented
Nov 6, 2023
Here's an alternative patch making use of diff --git c/taskw/taskrc.py w/taskw/taskrc.py
index 1b6f8e5..b72dee6 100644
--- c/taskw/taskrc.py+++ w/taskw/taskrc.py@@ -1,5 +1,6 @@
import logging
import os
from taskw.fields import (
ChoiceField,
@@ -39,6 +40,7 @@ class TaskRc(dict):
"""
+ rcdir = None
UDA_TYPE_MAP = {
'date': DateField,
'duration': DurationField,
@@ -54,6 +56,8 @@ class TaskRc(dict):
path
)
)
+ if not self.rcdir:+ TaskRc.rcdir = os.path.dirname(os.path.realpath(self.path))
config = self._read(self.path)
else:
self.path = None
@@ -92,6 +96,17 @@ class TaskRc(dict):
def _read(self, path):
config = {}
+ if not os.path.exists(path) and TaskRc.rcdir is not None:+ # include path may be given relative to dir of rcfile+ oldpath = path+ path = os.path.join(TaskRc.rcdir, oldpath)+ if not os.path.exists(path):+ logger.error(+ "rcfile does not exist, tried %s and %s",+ oldpath, path+ )+ raise FileNotFoundError+
with open(path, 'r') as config_file:
for raw_line in config_file.readlines():
line = sanitize(raw_line) |
RaitoBezarius
commented
Nov 6, 2023
I also sent a PR downstream in nixpkgs to apply the patch for the time being: NixOS/nixpkgs#265899. |
Actually, you need at least: diff --git c/taskw/taskrc.py w/taskw/taskrc.py
index 1b6f8e5..9a6610e 100644
--- c/taskw/taskrc.py+++ w/taskw/taskrc.py@@ -1,5 +1,6 @@
import logging
import os
+import shutil
from taskw.fields import (
ChoiceField,
@@ -39,6 +40,7 @@ class TaskRc(dict):
"""
+ rcdir = None
UDA_TYPE_MAP = {
'date': DateField,
'duration': DurationField,
@@ -48,16 +50,31 @@ class TaskRc(dict):
def __init__(self, path=None, overrides=None):
self.overrides = overrides if overrides else {}
+ binary_path = shutil.which("task")+ share_rc_path = None+ if binary_path is not None:+ binary_path = os.path.realpath(binary_path) # Normalizes any potential symlinks.+ prefix = os.path.dirname(os.path.dirname(binary_path)) # $prefix/bin/task → $prefix+ share_rc_path = os.path.join(prefix, "share", "doc", "task", "rc") # $prefix/share/doc/task/rc contains additional files.++ self.fallback_prefixes = list(filter(None, [+ share_rc_path+ ]))+
if path:
self.path = os.path.normpath(
os.path.expanduser(
path
)
)
+ if not self.rcdir:+ TaskRc.rcdir = os.path.dirname(os.path.realpath(self.path))+ self.fallback_prefixes.append(TaskRc.rcdir)
config = self._read(self.path)
else:
self.path = None
config = {}
+
super(TaskRc, self).__init__(config)
def _add_to_tree(self, config, key, value):
@@ -92,6 +109,28 @@ class TaskRc(dict):
def _read(self, path):
config = {}
++ if not os.path.exists(path):+ # include path may be given relative to dir of rcfile+ oldpath = path+ tries = []+ for fallback_prefix in self.fallback_prefixes:+ path = os.path.join(fallback_prefix, oldpath)+ if not os.path.exists(path):+ tries.append(path)+ logger.warn(+ "tried %s and %s with no success",+ oldpath, path+ )+ else:+ break+ if len(tries) == self.fallback_prefixes:+ logger.error(+ "failed to find a fallback prefix for %s",+ oldpath+ )+ raise FileNotFoundError+
with open(path, 'r') as config_file:
for raw_line in config_file.readlines():
line = sanitize(raw_line)to make this work for cases where the relative path is related to the default share data installed as part of TaskWarrior. |
1. from the CWD (deprecated behavior in taskwarrior)
2. in $TASK_RCDIR (custom path - just to allow flexibility from the end-user side
3. relative to the TASKRC file
4. in `{/usr/,/usr/local/}/share/doc/task/rc/`
This fixes the taskw repo bug
ralphbean/taskw#150 . See also the relevant PR
discussion in ralphbean/taskw#151bergercookie
commented
Jan 22, 2024
Hi all, I'm attempting to fix this issue in my taskw-ng fork (since AFAICT development has stalled unfortunately in this repo) Anyone knows what' the use of the |
smemsh
commented
Jun 21, 2024
@bergercookie not sure what you mean by "what's the use," |
smemsh
commented
Aug 26, 2025
marking this as superseded by #170 since I'm no longer using this library and the author of that one appears to still be active. |
Taskwarrior can have 'include' directives in the rcfile which use pathnames relative to the rcfile location. Currently in taskw library, these will fail because the file is opened without attempting to search for it or qualify the path beyond expanding tildes and normalizing the path. It only can work if given as absolute path or if the file is in cwd of process executing the library code.
With this PR, if we try to load the file and it doesn't exist, we will try it again as a path in the rcfile directory. This will work in most cases of a relative path and follows the same algorithm as TaskWarrior itself (partial implementation: TaskWarrior also tries other places, see commit message for details).
Fixes#150
(superseded by #170)