Version 11 of namespace import

Updated 2014-06-22 21:24:53 by pooryorick

namespace import imports commands into a namespace.

Synopsis

namespace import ?-force? ?pattern pattern ...?

Documentation

namespace man page

Description

Each pattern is a qualified name, e.g. foo::x or a::p*. That is, it includes the name of an exporting namespace and may have glob-style special characters in the command name at the end of the qualified name. Glob characters may not appear in a namespace name. All the commands that match a pattern and which are currently exported from their namespace are added to the current namespace. This is done by creating a new command in the current namespace that points to the exported command in its original namespace; when the new imported command is called, it invokes the exported command. This command normally returns an error if an imported command conflicts with an existing command. However, if the -force option is given, imported commands will silently replace existing commands. namespace import command has snapshot semantics: Only requested commands that are currently defined in the exporting namespace are imported. In other words, you can import only the commands that are in a namespace at the time when namespace import is executed. If another command is defined and exported in this namespace later on, it will not be imported.

For use cases where it is an alternative, namespace path is preferred to namespace import. (PYK 2014-06-22: rationale needed).

Copying Imports

PYK 2014-06-22: Here is a proc to copy all the imports from one namespace to another. The new imports link directly to the origin, not to the imported commands in $fromns

proc copyimports {fromns tons args} {
    set copied {}
    foreach name [info commands ${fromns}::*] {
        set origin [namespace eval $fromns [list namespace origin $name]]
        if {[namespace which ${tons}::[namespace tail $origin]] ne {}} {
            #command already exists in tons 
            continue
        }
        if {[llength $args] && [namespace tail $origin] ni $args} {
            #a list of specific commands was given, and this is not one of them
            #don't import it
            continue
        }
        set exports [namespace eval [
            namespace qualifiers $origin] namespace export]
        namespace eval [namespace qualifiers $origin] [list namespace export [
            namespace tail $origin]]

        namespace eval $tons [list namespace import $origin]
        lappend copied $origin
        namespace eval [namespace qualifiers $origin] [
            list namespace export -clear {*}$exports] 
    }
    return $copied
}

Misc

escargo 2006-12-04: I tested this to see what namespace import returns, and it didn't return anything. There are two behaviors that I think might be useful that aren't implemented:

  1. Have namespace import return a list of the commands that are imported. Right now I don't see any easy way to determine what gets imported. (DKF: This is what 8.5 now does, BTW.) (What TIP 261 specifies is the behavior with no arguments. That's not quite what I'm suggesting.)
  2. Alternatively, have namespace import take another parameter, perhaps -asif, that tells the it to just return the names of what would be imported and to not do the actual import.

My motivation has to do with Nagelfar, actually. The second option would allow a code analyzer to follow along with "package require" and "namespace import" to discover code that would be known to the code being analyzed. This would allow reduction of false positives for unknown commands.

See Also

namespace