Tcl Source Code

View Ticket
Login
Ticket UUID: 560297
Title: [namespace forget] matches by name only
Type: Bug Version: obsolete: 8.4a4
Submitter: msofer Created on: 2002-05-24 20:18:14
Subsystem: 21. [namespace] Assigned To: dgp
Priority: 8 Severity:
Status: Closed Last Modified: 2004-09-09 22:44:51
Resolution: Fixed Closed By: dgp
    Closed on: 2004-09-09 15:44:51
Description:
As documented in [Bug #559268], the behaviour of
[namespace forget] is somewhat surprising:

(1)  it may forget a command imported from a different
namespace

% namespace eval src0 {proc a {} {puts 0}}
% namespace eval src0 {namespace export a}
% namespace eval src1 {proc a {} {puts 1}}
% namespace eval tst {namespace import ::src0::a}
% tst::a
0
% namespace eval tst {namespace forget ::src1::a}
% tst::a
invalid command name "tst::a"

(2)  it fails to forget an imported command if it was
renamed

% namespace eval src {proc a {} {puts 1}}
% namespace eval src {namespace export a}
% namespace eval dst {namespace import ::src::a}
% namespace eval dst {rename a b}
% dst::b
1
% namespace eval dst {namespace forget ::src::a}
% dst::b
1
User Comments: dgp added on 2004-09-09 22:44:51:
Logged In: YES 
user_id=80530

Patch -3 committed along with some
new tests.  commit to HEAD and 8.4 branch.

dgp added on 2004-09-01 00:07:07:

File Added - 99875: 560297-3.patch

Logged In: YES 
user_id=80530

New patch implements 
option 3)

no more failed tests.

dgp added on 2004-08-31 23:18:22:
Logged In: YES 
user_id=80530


the failing test raises the question
of how to forget import chains.

% namespace eval origin {  
    namespace export cmd
    proc cmd args {}
}
% namespace eval link {
    namespace export cmd
    namespace import origin::cmd
}
% namespace eval unrelated {
    namespace export cmd
    proc cmd args {}
}
% namespace eval my namespace import ::link::cmd

At this point, in an unpatched Tcl, any of
the following commands in namespace "my"
will forget my::cmd :

namespace forget ::origin::cmd
namespace forget ::link:::cmd
namespace forget ::unrelated::cmd

The last is case (1) in the bug report.

After the attached patch is applied,
only

namespace forget ::origin::cmd

will work.

The test fails because it would
expect that

namespace forget ::link::cmd 

would also work, and that has
some intuitive appeal as well,
as that is really the command
that was imported.

So we have some options
how to deal with the links in
an import chain:

1) forget based only on the origin.
  - what the patch does
2) forget based only on the first link
  - closer in intuition to being the
    inverse of a [namespace import]
3) Both 1) and 2)
  - allow forgetting by either 1st or last
4) forget based on any link in the chain at all

Advantage of 1) is that it means
    [namespace forget [namespace origin $cmd]]
is always a reliable operation.
Advantage of including 2) as well is that
there will be no failing tests, and it's
more intuitive
So, I think I like 3)

Should probably be said that this whole
realm is likely best avoided by using
[namespace forget $simpleName]
whenever possible.

dgp added on 2004-08-31 22:36:23:

File Added - 99853: 560297.patch

dgp added on 2004-08-31 22:36:21:
Logged In: YES 
user_id=80530

here's a patch that implements
the outline posted before.

One wrinkle: namespace-old-9.14 fails.

NOTE: Patch 1019718 is included
in the attached patch.

dgp added on 2004-08-31 20:28:51:
Logged In: YES 
user_id=80530

Refinement of the definition:

An "imported command" is any
for which
[namespace which -command $cmd]
and
[namespace origin $cmd]
produce different results.

dgp added on 2004-08-28 05:08:27:
Logged In: YES 
user_id=80530


It is the function of [namespace forget]
to delete imported command(s)
from the current namespace of the interp,
based on pattern arguments.

An "imported command" is any for
which {$cmd ne [namespace origin $cmd]}.

Simple patterns (no namespace separator)
should match against simple names of
imported commands and delete those
that match.  This means problem (3)
isn't really a problem at all.  Whether the
imported command got into the current
namespace via [namespace import] or
[rename] shouldn't really matter.

For namespace qualified patterns, the
apparent intent is to control deletion
of import command based on where
they point to.  Based on that, is seems
the correct behavior is to loop over the
imported commands in the current
namespace, determine the [namespace origin]
of each, and match that against the qualified
pattern.  That algoritthm would correct
problems (1) and (2).

msofer added on 2002-05-25 04:15:40:
Logged In: YES 
user_id=148712

Kevin Kenny spotted another problem:

(3) it may remove a command that was *not* imported into the
current namespace:

% namespace eval src {proc a {} {puts 1}}
% namespace eval src {namespace export a}
% namespace eval dst {namespace import ::src::a}
% namespace eval dst1 {}
% namespace eval dst {rename a ::dst1::b}
% dst1::b
1
% namespace eval dst1 {namespace forget b}
%  dst1::b
invalid command name "dst1::b"

Attachments: