diff --git a/datalad/cmdline/main.py b/datalad/cmdline/main.py
index 085d7909e..ea36b369a 100644
--- a/datalad/cmdline/main.py
+++ b/datalad/cmdline/main.py
@@ -175,30 +175,12 @@ def setup_parser(
         of the command; 'continue' works like 'ignore', but an error causes a
         non-zero exit code; 'stop' halts on first failure and yields non-zero exit
         code. A failure is any result with status 'impossible' or 'error'.""")
-    parser.add_argument(
-        '--proc-pre', dest='common_proc_pre',
-        nargs='+',
-        action='append',
-        metavar=('<PROCEDURE NAME>', 'ARGS'),
-        help="""Dataset procedure to run before the main command (see run-procedure
-        command for details). This option can be given more than once to run
-        multiple procedures in the order in which they were given.
-        It is important to specify the target dataset via the --dataset argument
-        of the main command."""),
-    parser.add_argument(
-        '--proc-post', dest='common_proc_post',
-        nargs='+',
-        action='append',
-        metavar=('<PROCEDURE NAME>', 'ARGS'),
-        help="""Like --proc-pre, but procedures are executed after the main command
-        has finished."""),
     parser.add_argument(
         '--cmd', dest='_', action='store_true',
         help="""syntactical helper that can be used to end the list of global
-        command line options before the subcommand label. Options like
-        --proc-pre can take an arbitrary number of arguments and may require
-        to be followed by a single --cmd in order to enable identification
-        of the subcommand.""")
+        command line options before the subcommand label. Options taking
+        an arbitrary number of arguments may require to be followed by a single
+        --cmd in order to enable identification of the subcommand.""")
 
     # yoh: atm we only dump to console.  Might adopt the same separation later on
     #      and for consistency will call it --verbose-level as well for now
diff --git a/datalad/interface/base.py b/datalad/interface/base.py
index dc87ac6d8..ff3685d69 100644
--- a/datalad/interface/base.py
+++ b/datalad/interface/base.py
@@ -681,7 +681,7 @@ class Interface(object):
             # XXX define or better get from elsewhere
             common_opts = ('change_path', 'common_debug', 'common_idebug', 'func',
                            'help', 'log_level', 'logger', 'pbs_runner',
-                           'result_renderer', 'proc_pre', 'proc_post', 'subparser')
+                           'result_renderer', 'subparser')
             argnames = [name for name in dir(args)
                         if not (name.startswith('_') or name in common_opts)]
         kwargs = {k: getattr(args, k) for k in argnames if is_api_arg(k)}
@@ -712,8 +712,6 @@ class Interface(object):
                 # eval_results can't distinguish between --report-{status,type}
                 # not specified via the CLI and None passed via the Python API.
                 kwargs['result_filter'] = res_filter
-            kwargs['proc_pre'] = args.common_proc_pre
-            kwargs['proc_post'] = args.common_proc_post
         try:
             ret = cls.__call__(**kwargs)
             if inspect.isgenerator(ret):
diff --git a/datalad/interface/common_opts.py b/datalad/interface/common_opts.py
index e02fd0ac4..d2da17f0d 100644
--- a/datalad/interface/common_opts.py
+++ b/datalad/interface/common_opts.py
@@ -308,15 +308,6 @@ eval_params = dict(
         that carries the result dictionaries of the failures in its `failed`
         attribute.""",
         constraints=EnsureChoice('ignore', 'continue', 'stop')),
-    proc_pre=Parameter(
-        doc="""DataLad procedure to run prior to the main command. The argument
-        a list of lists with procedure names and optional arguments.
-        Procedures are called in the order their are given in this list.
-        It is important to provide the respective target dataset to run a procedure
-        on as the `dataset` argument of the main command."""),
-    proc_post=Parameter(
-        doc="""Like `proc_pre`, but procedures are executed after the main command
-        has finished."""),
 )
 
 eval_defaults = dict(
@@ -325,6 +316,4 @@ eval_defaults = dict(
     result_renderer=None,
     result_xfm=None,
     on_failure='continue',
-    proc_pre=None,
-    proc_post=None,
 )
diff --git a/datalad/interface/run_procedure.py b/datalad/interface/run_procedure.py
index 6529ad38b..11827742f 100644
--- a/datalad/interface/run_procedure.py
+++ b/datalad/interface/run_procedure.py
@@ -275,26 +275,6 @@ class RunProcedure(Interface):
     - 'datalad.procedures.<NAME>.help'
       will be shown on `datalad run-procedure --help-proc NAME` to provide a
       description and/or usage info for procedure NAME
-
-    *Customize other commands with procedures*
-
-    On execution of any commands, DataLad inspects two additional
-    configuration settings:
-
-    - 'datalad.<name>.proc-pre'
-
-    - 'datalad.<name>.proc-post'
-
-    where '<name>' is the name of a DataLad command. Using this mechanism
-    DataLad can be instructed to run one or more procedures before or
-    after the execution of a given command. For example, configuring
-    a set of metadata types in any newly created dataset can be achieved
-    via:
-
-      % datalad -c 'datalad.create.proc-post=cfg_metadatatypes xmp image' create -d myds
-
-    As procedures run on datasets, it is necessary to explicitly identify
-    the target dataset via the -d (--dataset) option.
     """
     _params_ = dict(
         spec=Parameter(
diff --git a/datalad/interface/utils.py b/datalad/interface/utils.py
index ab5dee7a4..4c4278f86 100644
--- a/datalad/interface/utils.py
+++ b/datalad/interface/utils.py
@@ -33,18 +33,19 @@ import json
 
 # avoid import from API to not get into circular imports
 from datalad.utils import with_pathsep as _with_sep  # TODO: RF whenever merge conflict is not upon us
-from datalad.utils import path_startswith
-from datalad.utils import path_is_subpath
-from datalad.utils import assure_unicode
-from datalad.utils import getargspec
+from datalad.utils import (
+    path_startswith,
+    path_is_subpath,
+    assure_unicode,
+    getargspec,
+    get_wrapped_class,
+)
 from datalad.support.gitrepo import GitRepo
 from datalad.support.exceptions import IncompleteResultsError
 from datalad import cfg as dlcfg
 from datalad.dochelpers import exc_str
 
 
-from datalad.support.constraints import Constraint
-
 from datalad.ui import ui
 import datalad.support.ansi_colors as ac
 
@@ -265,6 +266,16 @@ def discover_dataset_trace_to_targets(basepath, targetpaths, current_trace,
                 undiscovered_ds)
 
 
+def get_result_filter(fx):
+    """Wrap a filter into a helper to be able to accept additional
+    arguments, if the filter doesn't support it already"""
+    _fx = fx
+    if fx and not getargspec(fx).keywords:
+        def _fx(res, **kwargs):
+            return fx(res)
+    return _fx
+
+
 def eval_results(func):
     """Decorator for return value evaluation of datalad commands.
 
@@ -309,70 +320,49 @@ def eval_results(func):
     @wrapt.decorator
     def eval_func(wrapped, instance, args, kwargs):
         lgr.log(2, "Entered eval_func for %s", func)
-        # for result filters and pre/post procedures
+        # for result filters
         # we need to produce a dict with argname/argvalue pairs for all args
         # incl. defaults and args given as positionals
         allkwargs = get_allargs_as_kwargs(wrapped, args, kwargs)
-        # determine class, the __call__ method of which we are decorating:
-        mod = sys.modules[wrapped.__module__]
-        command_class_name = wrapped.__qualname__.split('.')[-2]
-        _func_class = mod.__dict__[command_class_name]
-        lgr.debug("Determined class of decorated function: %s", _func_class)
+
+        # determine the command class associated with `wrapped`
+        wrapped_class = get_wrapped_class(wrapped)
 
         # retrieve common options from kwargs, and fall back on the command
         # class attributes, or general defaults if needed
         kwargs = kwargs.copy()  # we will pop, which might cause side-effect
         common_params = {
             p_name: kwargs.pop(
+                # go with any explicitly given default
                 p_name,
-                getattr(_func_class, p_name, eval_defaults[p_name]))
+                # otherwise determine the command class and pull any
+                # default set in that class
+                getattr(
+                    wrapped_class,
+                    p_name,
+                    # or the common default
+                    eval_defaults[p_name]))
             for p_name in eval_params}
+
         # short cuts and configured setup for common options
-        on_failure = common_params['on_failure']
         return_type = common_params['return_type']
+        result_filter = get_result_filter(common_params['result_filter'])
         # resolve string labels for transformers too
-        result_xfm = common_params['result_xfm']
-        if result_xfm in known_result_xfms:
-            result_xfm = known_result_xfms[result_xfm]
+        result_xfm = known_result_xfms.get(
+            common_params['result_xfm'],
+            # use verbatim, if not a known label
+            common_params['result_xfm'])
         result_renderer = common_params['result_renderer']
         # TODO remove this conditional branch entirely, done outside
         if not result_renderer:
             result_renderer = dlcfg.get('datalad.api.result-renderer', None)
         # look for potential override of logging behavior
         result_log_level = dlcfg.get('datalad.log.result-level', None)
-        # wrap the filter into a helper to be able to pass additional arguments
-        # if the filter supports it, but at the same time keep the required interface
-        # as minimal as possible. Also do this here, in order to avoid this test
-        # to be performed for each return value
-        result_filter = common_params['result_filter']
-        _result_filter = result_filter
-        if result_filter:
-            if isinstance(result_filter, Constraint):
-                _result_filter = result_filter.__call__
-            if getargspec(_result_filter).keywords:
-                def _result_filter(res):
-                    return result_filter(res, **allkwargs)
-
-        def _get_procedure_specs(param_key=None, cfg_key=None, ds=None, proc_cfg=None):
-            lgr.log(2, "Getting procedure specs for %s of %s", param_key, ds)
-            spec = common_params.get(param_key, None)
-            if spec is not None:
-                # this is already a list of lists
-                return spec
-
-            spec = proc_cfg.get(cfg_key, None)
-            if spec is None:
-                return None
-            elif not isinstance(spec, tuple):
-                spec = [spec]
-            return [shlex.split(s) for s in spec]
 
         # query cfg for defaults
-        cmdline_name = cls2cmdlinename(_func_class)
-        dataset_arg = allkwargs.get('dataset', None)
-
         # .is_installed and .config can be costly, so ensure we do
         # it only once. See https://github.com/datalad/datalad/issues/3575
+        dataset_arg = allkwargs.get('dataset', None)
         from datalad.distribution.dataset import Dataset
         ds = dataset_arg if isinstance(dataset_arg, Dataset) \
             else Dataset(dataset_arg) if dataset_arg else None
@@ -388,17 +378,6 @@ def eval_results(func):
             ds, source='local', overrides=dlcfg.overrides
         ) if ds and ds.is_installed() else dlcfg
 
-        proc_pre = _get_procedure_specs(
-            'proc_pre',
-            'datalad.{}.proc-pre'.format(cmdline_name),
-            ds=dataset_arg,
-            proc_cfg=proc_cfg)
-        proc_post = _get_procedure_specs(
-            'proc_post',
-            'datalad.{}.proc-post'.format(cmdline_name),
-            ds=dataset_arg,
-            proc_cfg=proc_cfg)
-
         # look for hooks
         hooks = get_jsonhooks_from_config(proc_cfg)
 
@@ -411,35 +390,26 @@ def eval_results(func):
             # track what actions were performed how many times
             action_summary = {}
 
-            if proc_pre and cmdline_name != 'run-procedure':
-                from datalad.interface.run_procedure import RunProcedure
-                for procspec in proc_pre:
-                    lgr.debug('Running configured pre-procedure %s', procspec)
-                    for r in _process_results(
-                            RunProcedure.__call__(
-                                procspec,
-                                dataset=dataset_arg,
-                                return_type='generator'),
-                            _func_class, action_summary,
-                            on_failure, incomplete_results,
-                            result_renderer, result_xfm, result_filter,
-                            result_log_level,
-                            **_kwargs):
-                        yield r
-
             # if a custom summary is to be provided, collect the results
             # of the command execution
             results = []
             do_custom_result_summary = result_renderer == 'tailored' \
-                and hasattr(_func_class, 'custom_result_summary_renderer')
+                and hasattr(wrapped_class, 'custom_result_summary_renderer')
 
             # process main results
             for r in _process_results(
+                    # execution
                     wrapped(*_args, **_kwargs),
-                    _func_class, action_summary,
-                    on_failure, incomplete_results,
-                    result_renderer, result_xfm, _result_filter,
-                    result_log_level, **_kwargs):
+                    wrapped_class,
+                    common_params['on_failure'],
+                    # bookkeeping
+                    action_summary,
+                    incomplete_results,
+                    # communication
+                    result_renderer,
+                    result_log_level,
+                    # let renderers get to see how a command was called
+                    allkwargs):
                 for hook, spec in hooks.items():
                     # run the hooks before we yield the result
                     # this ensures that they are executed before
@@ -453,31 +423,34 @@ def eval_results(func):
                         # loops, i.e. when a hook yields a result that
                         # triggers that same hook again
                         for hr in run_jsonhook(hook, spec, r, dataset_arg):
-                            yield hr
-                yield r
+                            # apply same logic as for main results, otherwise
+                            # any filters would only tackle the primary results
+                            # and a mixture of return values could happen
+                            if not keep_result(hr, result_filter, **allkwargs):
+                                continue
+                            hr = xfm_result(hr, result_xfm)
+                            # rationale for conditional is a few lines down
+                            if hr:
+                                yield hr
+                if not keep_result(r, result_filter, **allkwargs):
+                    continue
+                r = xfm_result(r, result_xfm)
+                # in case the result_xfm decided to not give us anything
+                # exclude it from the results. There is no particular reason
+                # to do so other than that it was established behavior when
+                # this comment was written. This will not affect any real
+                # result record
+                if r:
+                    yield r
+
                 # collect if summary is desired
                 if do_custom_result_summary:
                     results.append(r)
 
-            if proc_post and cmdline_name != 'run-procedure':
-                from datalad.interface.run_procedure import RunProcedure
-                for procspec in proc_post:
-                    lgr.debug('Running configured post-procedure %s', procspec)
-                    for r in _process_results(
-                            RunProcedure.__call__(
-                                procspec,
-                                dataset=dataset_arg,
-                                return_type='generator'),
-                            _func_class, action_summary,
-                            on_failure, incomplete_results,
-                            result_renderer, result_xfm, result_filter,
-                            result_log_level, **_kwargs):
-                        yield r
-
             # result summary before a potential exception
             # custom first
             if do_custom_result_summary:
-                _func_class.custom_result_summary_renderer(results)
+                wrapped_class.custom_result_summary_renderer(results)
             elif result_renderer == 'default' and action_summary and \
                     sum(sum(s.values()) for s in action_summary.values()) > 1:
                 # give a summary in default mode, when there was more than one
@@ -496,7 +469,7 @@ def eval_results(func):
 
         if return_type == 'generator':
             # hand over the generator
-            lgr.log(2, "Returning generator_func from eval_func for %s", _func_class)
+            lgr.log(2, "Returning generator_func from eval_func for %s", wrapped_class)
             return generator_func(*args, **kwargs)
         else:
             @wrapt.decorator
@@ -509,14 +482,14 @@ def eval_results(func):
                 # render summaries
                 if not result_xfm and result_renderer == 'tailored':
                     # cannot render transformed results
-                    if hasattr(_func_class, 'custom_result_summary_renderer'):
-                        _func_class.custom_result_summary_renderer(results)
+                    if hasattr(wrapped_class, 'custom_result_summary_renderer'):
+                        wrapped_class.custom_result_summary_renderer(results)
                 if return_type == 'item-or-list' and \
                         len(results) < 2:
                     return results[0] if results else None
                 else:
                     return results
-            lgr.log(2, "Returning return_func from eval_func for %s", _func_class)
+            lgr.log(2, "Returning return_func from eval_func for %s", wrapped_class)
             return return_func(generator_func)(*args, **kwargs)
 
     return eval_func(func)
@@ -541,10 +514,14 @@ def default_result_renderer(res):
 
 
 def _process_results(
-        results, cmd_class,
-        action_summary, on_failure, incomplete_results,
-        result_renderer, result_xfm, result_filter,
-        result_log_level, **kwargs):
+        results,
+        cmd_class,
+        on_failure,
+        action_summary,
+        incomplete_results,
+        result_renderer,
+        result_log_level,
+        allkwargs):
     # private helper pf @eval_results
     # loop over results generated from some source and handle each
     # of them according to the requested behavior (logging, rendering, ...)
@@ -601,10 +578,10 @@ def _process_results(
                 default=lambda x: str(x)))
         elif result_renderer == 'tailored':
             if hasattr(cmd_class, 'custom_result_renderer'):
-                cmd_class.custom_result_renderer(res, **kwargs)
+                cmd_class.custom_result_renderer(res, **allkwargs)
         elif hasattr(result_renderer, '__call__'):
             try:
-                result_renderer(res, **kwargs)
+                result_renderer(res, **allkwargs)
             except Exception as e:
                 lgr.warning('Result rendering failed for: %s [%s]',
                             res, exc_str(e))
@@ -621,18 +598,27 @@ def _process_results(
                 # first fail -> that's it
                 # raise will happen after the loop
                 break
+        yield res
 
-        if result_filter:
-            try:
-                if not result_filter(res):
-                    raise ValueError('excluded by filter')
-            except ValueError as e:
-                lgr.debug('not reporting result (%s)', exc_str(e))
-                continue
 
-        if result_xfm:
-            res = result_xfm(res)
-            if res is None:
-                continue
+def keep_result(res, rfilter, **kwargs):
+    if not rfilter:
+        return True
+    try:
+        if not rfilter(res, **kwargs):
+            # give the slightest indication which filter was employed
+            raise ValueError(
+                'excluded by filter {} with arguments {}'.format(rfilter, kwargs))
+    except ValueError as e:
+        # make sure to report the excluded result to massively improve
+        # debugging experience
+        lgr.debug('Not reporting result (%s): %s', exc_str(e), res)
+        return False
+    return True
 
-        yield res
+
+def xfm_result(res, xfm):
+    if not xfm:
+        return res
+
+    return xfm(res)
diff --git a/datalad/utils.py b/datalad/utils.py
index ce8e85029..9eb7f1bc0 100644
--- a/datalad/utils.py
+++ b/datalad/utils.py
@@ -2320,6 +2320,15 @@ def maybe_shlex_quote(val):
     return val if on_windows else shlex_quote(val)
 
 
+def get_wrapped_class(wrapped):
+    """Determine the command class a wrapped __call__ belongs to"""
+    mod = sys.modules[wrapped.__module__]
+    command_class_name = wrapped.__qualname__.split('.')[-2]
+    _func_class = mod.__dict__[command_class_name]
+    lgr.debug("Determined class of decorated function: %s", _func_class)
+    return _func_class
+
+
 # TODO whenever we feel ready for English kill the compat block below
 assure_tuple_or_list = ensure_tuple_or_list
 assure_iter = ensure_iter

Remove --proc-pre/post (replacement: result hooks)
This new feature is proposed in https://github.com/datalad/datalad/pull/3903

I propose to remove its predecessors, because their are (from my POV) completely unused, untested, and less capable (only dataset procedures, not any DataLad command). 
diff --git a/datalad/core/local/tests/test_create.py b/datalad/core/local/tests/test_create.py
index e9b1fe2bc..044f8ebd4 100644
--- a/datalad/core/local/tests/test_create.py
+++ b/datalad/core/local/tests/test_create.py
@@ -385,24 +385,6 @@ def test_saving_prior(topdir):
     assert_in('ds2', ds1.subdatasets(result_xfm='relpaths'))
 
 
-@with_tempfile(mkdir=True)
-def test_create_withprocedure(path):
-    # first without
-    ds = create(path)
-    assert(not op.lexists(op.join(ds.path, 'README.rst')))
-    ds.remove()
-    assert(not op.lexists(ds.path))
-    # now for reals...
-    ds = create(
-        # needs to identify the dataset, otherwise post-proc
-        # procedure doesn't know what to run on
-        dataset=path,
-        proc_post=[['cfg_metadatatypes', 'xmp', 'datacite']])
-    assert_repo_status(path)
-    ds.config.reload()
-    eq_(ds.config['datalad.metadata.nativetype'], ('xmp', 'datacite'))
-
-
 @with_tempfile(mkdir=True)
 def test_create_withcfg(path):
     ds = create(
diff --git a/datalad/core/local/tests/test_resulthooks.py b/datalad/core/local/tests/test_resulthooks.py
index f4581a86c..3b0f03481 100644
--- a/datalad/core/local/tests/test_resulthooks.py
+++ b/datalad/core/local/tests/test_resulthooks.py
@@ -31,6 +31,8 @@ def test_basics(src, dst):
     (ds.pathobj / 'file1').write_text('some')
     ds.save()
     sub = ds.create('subds')
+    # second one for a result_xfm test below
+    ds.create('subds2')
     eq_(sub.config.get('datalad.metadata.nativetype'), None)
 
     # now clone the super
@@ -39,8 +41,6 @@ def test_basics(src, dst):
     # on install to have 'bids' listed as a metadata type
     clone.config.set(
         'datalad.result-hook.alwaysbids.call-json',
-        # the spec is like --proc-post/pre, but has the dataset to run on as
-        # the first element
         # string substitutions based on the result record are supported
         'run_procedure {{"dataset":"{path}","spec":"cfg_metadatatypes bids"}}',
         where='local',
@@ -88,11 +88,14 @@ def test_basics(src, dst):
             '{"type":["in", ["file"]],"action":"get","status":"notneeded"}',
             where='local',
         )
-    # TODO resetting of detached HEAD seem to come after the install result
-    # and wipes out the change
+    # setup done, now see if it works
     clone.get('subds')
     clone_sub = Dataset(clone.pathobj / 'subds')
     eq_(clone_sub.config.get('datalad.metadata.nativetype'), 'bids')
+    # now the same thing with a result_xfm, should make no difference
+    clone.get('subds2')
+    clone_sub2 = Dataset(clone.pathobj / 'subds2')
+    eq_(clone_sub2.config.get('datalad.metadata.nativetype'), 'bids')
 
     # hook auto-unlocks the file
     if not on_windows:
diff --git a/datalad/interface/tests/test_base.py b/datalad/interface/tests/test_base.py
index d238b97cc..c7dd0d994 100644
--- a/datalad/interface/tests/test_base.py
+++ b/datalad/interface/tests/test_base.py
@@ -43,8 +43,6 @@ def _new_args(**kwargs):
                 common_on_failure=None,  # ['ignore', 'continue', 'stop']
                 common_report_status=None,  # ['all', 'success', 'failure', 'ok', 'notneeded', 'impossible', 'error']
                 common_report_type=None,  # ['dataset', 'file']
-                common_proc_pre=None,
-                common_proc_post=None,
             ),
             kwargs
         )
@@ -151,4 +149,4 @@ def test_nagen():
 def test_nadict():
     d = nadict({1: 2})
     eq_(d[1], 2)
-    eq_(str(d[2]), NA_STRING)
\ No newline at end of file
+    eq_(str(d[2]), NA_STRING)
diff --git a/datalad/interface/tests/test_run_procedure.py b/datalad/interface/tests/test_run_procedure.py
index ba895d0e2..cd928e0e8 100644
--- a/datalad/interface/tests/test_run_procedure.py
+++ b/datalad/interface/tests/test_run_procedure.py
@@ -70,57 +70,6 @@ def test_dirty(path):
     assert_repo_status(ds.path)
 
 
-@known_failure_windows  #FIXME
-@with_tree(tree={
-    'code': {'datalad_test_proc.py': """\
-import sys
-import os.path as op
-from datalad.api import save, Dataset
-
-with open(op.join(sys.argv[1], 'fromproc.txt'), 'w') as f:
-    f.write('hello\\n')
-save(dataset=Dataset(sys.argv[1]), path='fromproc.txt')
-"""}})
-@with_tempfile
-def test_basics(path, super_path):
-    ds = Dataset(path).create(force=True)
-    ds.run_procedure('cfg_yoda')
-    assert_false(ds.repo.is_under_annex("README.md"))
-    # save the procedure
-    ds.save('code')
-    # configure dataset to look for procedures in its code folder
-    ds.config.add(
-        'datalad.locations.dataset-procedures',
-        'code',
-        where='dataset')
-    # commit this procedure config for later use in a clone:
-    ds.save(op.join('.datalad', 'config'))
-    # configure dataset to run the demo procedure prior to the clean command
-    ds.config.add(
-        'datalad.clean.proc-pre',
-        'datalad_test_proc',
-        where='local')
-    # run command that should trigger the demo procedure
-    ds.clean()
-    # look for traces
-    ok_file_has_content(op.join(ds.path, 'fromproc.txt'), 'hello\n')
-
-    # make a fresh dataset:
-    super = Dataset(super_path).create()
-    # configure dataset to run the demo procedure prior to the clean command
-    super.config.add(
-        'datalad.clean.proc-pre',
-        'datalad_test_proc',
-        where='local')
-    # 'super' doesn't know any procedures but should get to know one by
-    # installing the above as a subdataset
-    super.install('sub', source=ds.path)
-    # run command that should trigger the demo procedure
-    super.clean()
-    # look for traces
-    ok_file_has_content(op.join(super.path, 'fromproc.txt'), 'hello\n')
-
-
 @skip_if(cond=on_windows and cfg.obtain("datalad.repo.version") < 6)
 @with_tree(tree={
     'code': {'datalad_test_proc.py': """\
@@ -160,11 +109,6 @@ def test_procedure_discovery(path, super_path):
         'datalad.locations.dataset-procedures',
         'code',
         where='dataset')
-    # configure dataset to run the demo procedure prior to the clean command
-    ds.config.add(
-        'datalad.clean.proc-pre',
-        'datalad_test_proc',
-        where='dataset')
     ds.save(op.join('.datalad', 'config'))
 
     # run discovery on the dataset:

pip install -e .[devel]
parse_log_pytest
requirements.txt
nose coverage pytest
apt-get update apt-get install -y gcc
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
alabaster==0.7.13
appdirs==1.4.4
asv==0.6.4
asv_runner==0.2.1
Babel==2.14.0
beautifulsoup4==4.13.3
boto==2.49.0
build==1.1.1
certifi @ file:///croot/certifi_1671487769961/work/certifi
cffi==1.15.1
chardet==5.2.0
charset-normalizer==3.4.1
citeproc-py==0.6.0
coverage==7.2.7
cryptography==44.0.2
-e git+https://github.com/datalad/datalad.git@c38dbd7f6b3eb71599f3ee76150231166486d9d7#egg=datalad
Deprecated==1.2.18
distlib==0.3.9
docutils==0.19
duecredit==0.9.3
exceptiongroup==1.2.2
ExifRead==3.0.0
fasteners==0.19
filelock==3.12.2
gitdb==4.0.12
GitPython==3.1.44
gprof2dot==2022.7.29
httpretty==1.1.4
humanize==4.6.0
idna==3.10
imagesize==1.4.1
importlib-metadata==6.7.0
importlib-resources==5.12.0
iniconfig==2.0.0
iso8601==2.1.0
jaraco.classes==3.2.3
jeepney==0.9.0
Jinja2==3.1.6
jsmin==3.0.1
json5==0.9.16
keyring==24.1.1
keyrings.alt==4.2.0
lxml==5.3.1
MarkupSafe==2.1.5
more-itertools==9.1.0
msgpack==1.0.5
multidict==6.0.5
mutagen==1.47.0
nose==1.3.7
nose-timer==1.0.1
packaging==24.0
patool==1.12
Pillow==9.5.0
platformdirs==4.0.0
pluggy==1.2.0
psutil==7.0.0
pycparser==2.21
PyGithub==2.3.0
Pygments==2.17.2
PyJWT==2.8.0
Pympler==1.1
PyNaCl==1.5.0
pypandoc==1.15
pyperclip==1.9.0
pyproject_hooks==1.2.0
pytest==7.4.4
python-dateutil==2.9.0.post0
python-xmp-toolkit==2.0.2
pytz==2025.2
PyYAML==6.0.1
requests==2.31.0
requests-ftp==0.3.1
SecretStorage==3.3.3
simplejson==3.20.1
six==1.17.0
smmap==5.0.2
snowballstemmer==2.2.0
soupsieve==2.4.1
Sphinx==5.3.0
sphinx-rtd-theme==2.0.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jquery==4.1
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
swebench-matterhorn @ file:///swebench_matterhorn
tabulate==0.9.0
tomli==2.0.1
tqdm==4.67.1
typing_extensions==4.7.1
urllib3==1.26.20
vcrpy==4.4.0
virtualenv==20.26.6
Whoosh==2.7.4
wrapt==1.16.0
yarl==1.9.4
zipp==3.15.0

name: datalad
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - appdirs==1.4.4
      - asv==0.6.4
      - asv-runner==0.2.1
      - babel==2.14.0
      - beautifulsoup4==4.13.3
      - boto==2.49.0
      - build==1.1.1
      - cffi==1.15.1
      - chardet==5.2.0
      - charset-normalizer==3.4.1
      - citeproc-py==0.6.0
      - coverage==7.2.7
      - cryptography==44.0.2
      - deprecated==1.2.18
      - distlib==0.3.9
      - docutils==0.19
      - duecredit==0.9.3
      - exceptiongroup==1.2.2
      - exifread==3.0.0
      - fasteners==0.19
      - filelock==3.12.2
      - gitdb==4.0.12
      - gitpython==3.1.44
      - gprof2dot==2022.7.29
      - httpretty==1.1.4
      - humanize==4.6.0
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==6.7.0
      - importlib-resources==5.12.0
      - iniconfig==2.0.0
      - iso8601==2.1.0
      - jaraco-classes==3.2.3
      - jeepney==0.9.0
      - jinja2==3.1.6
      - jsmin==3.0.1
      - json5==0.9.16
      - keyring==24.1.1
      - keyrings-alt==4.2.0
      - lxml==5.3.1
      - markupsafe==2.1.5
      - more-itertools==9.1.0
      - msgpack==1.0.5
      - multidict==6.0.5
      - mutagen==1.47.0
      - nose==1.3.7
      - nose-timer==1.0.1
      - packaging==24.0
      - patool==1.12
      - pillow==9.5.0
      - platformdirs==4.0.0
      - pluggy==1.2.0
      - psutil==7.0.0
      - pycparser==2.21
      - pygithub==2.3.0
      - pygments==2.17.2
      - pyjwt==2.8.0
      - pympler==1.1
      - pynacl==1.5.0
      - pypandoc==1.15
      - pyperclip==1.9.0
      - pyproject-hooks==1.2.0
      - pytest==7.4.4
      - python-dateutil==2.9.0.post0
      - python-xmp-toolkit==2.0.2
      - pytz==2025.2
      - pyyaml==6.0.1
      - requests==2.31.0
      - requests-ftp==0.3.1
      - secretstorage==3.3.3
      - simplejson==3.20.1
      - six==1.17.0
      - smmap==5.0.2
      - snowballstemmer==2.2.0
      - soupsieve==2.4.1
      - sphinx==5.3.0
      - sphinx-rtd-theme==2.0.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jquery==4.1
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - swebench-matterhorn==0.0.0
      - tabulate==0.9.0
      - tomli==2.0.1
      - tqdm==4.67.1
      - typing-extensions==4.7.1
      - urllib3==1.26.20
      - vcrpy==4.4.0
      - virtualenv==20.26.6
      - whoosh==2.7.4
      - wrapt==1.16.0
      - yarl==1.9.4
      - zipp==3.15.0
prefix: /opt/conda/envs/datalad

datalad/interface/tests/test_base.py::test_call_from_parser_default_args datalad/interface/tests/test_base.py::test_call_from_parser_result_filter
datalad/interface/tests/test_base.py::test_call_from_parser_old_style datalad/interface/tests/test_base.py::test_call_from_parser_old_style_generator datalad/interface/tests/test_base.py::test_get_result_filter_arg_vs_config datalad/interface/tests/test_base.py::test_nagen datalad/interface/tests/test_base.py::test_nadict
datalad/interface/run_procedure.py datalad/utils.py datalad/interface/utils.py datalad/interface/common_opts.py datalad/interface/base.py datalad/cmdline/main.py
datalad/interface/run_procedure.py datalad/utils.py datalad/interface/utils.py datalad/interface/common_opts.py datalad/interface/base.py datalad/cmdline/main.py