From: Florian Ragwitz Date: Fri, 23 Feb 2007 23:00:00 +0000 (+0100) Subject: Import namespace-clean-0.03.tar.gz. X-Git-Tag: 0.03^0 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=p5sagit%2Fnamespace-clean.git;a=commitdiff_plain;h=6c0ece9ba4e73a0f83be4fc6e92072995fd21696 Import namespace-clean-0.03.tar.gz. --- diff --git a/Changes b/Changes index 48090f0..9a7fc5f 100644 --- a/Changes +++ b/Changes @@ -1,4 +1,8 @@ + [0.03] Sat Feb 24 22:34:55 CET 2007 + - Minor comment and POD cleanups + - Tried to clarify how the module works + [0.02] Tue Feb 20 00:38:24 CET 2007 - Added unimport behaviour diff --git a/MANIFEST b/MANIFEST index 1daf5f9..6f9d8ac 100644 --- a/MANIFEST +++ b/MANIFEST @@ -22,3 +22,4 @@ t/lib/ExporterTest.pm t/lib/FunctionWipeout.pm t/lib/Inheritance.pm t/lib/Unimport.pm +Todo diff --git a/META.yml b/META.yml index aaea6eb..f79b98a 100644 --- a/META.yml +++ b/META.yml @@ -1,4 +1,4 @@ -abstract: Keep imports out of your namespace +abstract: Keep imports and functions out of your namespace author: Robert 'phaylon' Sedlacek build_requires: FindBin: 0 @@ -14,4 +14,4 @@ no_index: requires: Filter::EOF: 0.02 Symbol: 0 -version: 0.02 +version: 0.03 diff --git a/README b/README index c7f0827..ee8a034 100644 --- a/README +++ b/README @@ -1,33 +1,32 @@ NAME - namespace::clean - Keep imports out of your namespace + namespace::clean - Keep imports and functions out of your namespace VERSION - 0.02 + 0.03 SYNOPSIS package Foo; use warnings; use strict; - use Carp qw(croak); # will be removed + use Carp qw(croak); # 'croak' will be removed - sub bar { 23 } # will be removed + sub bar { 23 } # 'bar' will be removed + # remove all previously defined functions use namespace::clean; - sub baz { bar() } # still defined, 'bar' still bound + sub baz { bar() } # 'baz' still defined, 'bar' still bound + # begin to collection function names from here again no namespace::clean; - sub quux { baz() } # will be removed again + sub quux { baz() } # 'quux' will be removed + # remove all functions defined after the 'no' unimport use namespace::clean; - ### Will print: - # No - # No - # Yes - # No + # Will print: 'No', 'No', 'Yes' and 'No' print +(__PACKAGE__->can('croak') ? 'Yes' : 'No'), "\n"; print +(__PACKAGE__->can('bar') ? 'Yes' : 'No'), "\n"; print +(__PACKAGE__->can('baz') ? 'Yes' : 'No'), "\n"; @@ -39,13 +38,16 @@ DESCRIPTION When you define a function, or import one, into a Perl package, it will naturally also be available as a method. This does not per se cause problems, but it can complicate subclassing and, for example, plugin - classes that are included by loading them as base classes. + classes that are included via multiple inheritance by loading them as + base classes. The "namespace::clean" pragma will remove all previously declared or - imported symbols at the end of the current package's compile cycle. This - means that functions are already bound by their name, and calls to them - still work. But they will not be available as methods on your class or - instances. + imported symbols at the end of the current package's compile cycle. + Functions called in the package itself will still be bound by their + name, but they won't show up as methods on your class or instances. + + By unimporting via "no" you can tell "namespace::clean" to start + collecting functions for the next "use namespace::clean;" specification. METHODS You shouldn't need to call any of these. Just "use" the package at the @@ -53,8 +55,8 @@ METHODS import Makes a snapshot of the current defined functions and registers a - Filter::EOF cleanup routine to remove those symbols from the package at - the end of the compile-time. + Filter::EOF cleanup routine to remove those symbols at the end of the + compile-time. unimport This method will be called when you do a @@ -64,7 +66,7 @@ METHODS It will start a new section of code that defines functions to clean up. get_class_store - This returns a reference to a hash in your package containing + This returns a reference to a hash in a passed package containing information about function names included and excluded from removal. get_functions @@ -72,6 +74,21 @@ METHODS it as a hash reference with the function name as key and a typeglob reference to the symbol as value. +IMPLEMENTATION DETAILS + This module works through the effect that a + + delete $SomePackage::{foo}; + + will remove the "foo" symbol from $SomePackage for run time lookups + (e.g., method calls) but will leave the entry alive to be called by + already resolved names in the package itself. + + A test file has been added to the perl core to ensure that this + behaviour will be stable in future releases. + + Just for completeness sake, if you want to remove the symbol completely, + use "undef" instead. + SEE ALSO Filter::EOF diff --git a/Todo b/Todo new file mode 100644 index 0000000..247b99b --- /dev/null +++ b/Todo @@ -0,0 +1,5 @@ + + General Todo's + - Adding "use namespace::clean-start;" and "use namespace::clean-end;" + - Adding "use namespace::clean 'remove_after_compile';" exporting that + function allowing "remove_after_compiletime($class, \@functions);" diff --git a/lib/namespace/clean.pm b/lib/namespace/clean.pm index 434e2da..ac82f8b 100644 --- a/lib/namespace/clean.pm +++ b/lib/namespace/clean.pm @@ -2,7 +2,7 @@ package namespace::clean; =head1 NAME -namespace::clean - Keep imports out of your namespace +namespace::clean - Keep imports and functions out of your namespace =cut @@ -15,11 +15,11 @@ use Filter::EOF; =head1 VERSION -0.02 +0.03 =cut -$VERSION = 0.02; +$VERSION = 0.03; $STORAGE_VAR = '__NAMESPACE_CLEAN_STORAGE'; =head1 SYNOPSIS @@ -28,25 +28,24 @@ $STORAGE_VAR = '__NAMESPACE_CLEAN_STORAGE'; use warnings; use strict; - use Carp qw(croak); # will be removed + use Carp qw(croak); # 'croak' will be removed - sub bar { 23 } # will be removed + sub bar { 23 } # 'bar' will be removed + # remove all previously defined functions use namespace::clean; - sub baz { bar() } # still defined, 'bar' still bound + sub baz { bar() } # 'baz' still defined, 'bar' still bound + # begin to collection function names from here again no namespace::clean; - sub quux { baz() } # will be removed again + sub quux { baz() } # 'quux' will be removed + # remove all functions defined after the 'no' unimport use namespace::clean; - ### Will print: - # No - # No - # Yes - # No + # Will print: 'No', 'No', 'Yes' and 'No' print +(__PACKAGE__->can('croak') ? 'Yes' : 'No'), "\n"; print +(__PACKAGE__->can('bar') ? 'Yes' : 'No'), "\n"; print +(__PACKAGE__->can('baz') ? 'Yes' : 'No'), "\n"; @@ -59,40 +58,48 @@ $STORAGE_VAR = '__NAMESPACE_CLEAN_STORAGE'; When you define a function, or import one, into a Perl package, it will naturally also be available as a method. This does not per se cause problems, but it can complicate subclassing and, for example, plugin -classes that are included by loading them as base classes. +classes that are included via multiple inheritance by loading them as +base classes. The C pragma will remove all previously declared or imported symbols at the end of the current package's compile cycle. -This means that functions are already bound by their name, and calls to -them still work. But they will not be available as methods on your class -or instances. +Functions called in the package itself will still be bound by their +name, but they won't show up as methods on your class or instances. + +By unimporting via C you can tell C to start +collecting functions for the next C specification. =head1 METHODS You shouldn't need to call any of these. Just C the package at the appropriate place. +=cut + =head2 import Makes a snapshot of the current defined functions and registers a -L cleanup routine to remove those symbols from the package -at the end of the compile-time. +L cleanup routine to remove those symbols at the end +of the compile-time. =cut sub import { my ($pragma) = @_; + # calling class, all current functions and our storage my $cleanee = caller; my $functions = $pragma->get_functions($cleanee); my $store = $pragma->get_class_store($cleanee); + # register symbols for removal, if they have a CODE entry for my $f (keys %$functions) { next unless $functions->{ $f } and *{ $functions->{ $f } }{CODE}; $store->{remove}{ $f } = 1; } + # register EOF handler on first call to import unless ($store->{handler_is_installed}) { Filter::EOF->on_eof_call(sub { for my $f (keys %{ $store->{remove} }) { @@ -120,10 +127,12 @@ It will start a new section of code that defines functions to clean up. sub unimport { my ($pragma) = @_; + # the calling class, the current functions and our storage my $cleanee = caller; my $functions = $pragma->get_functions($cleanee); my $store = $pragma->get_class_store($cleanee); + # register all unknown previous functions as excluded for my $f (keys %$functions) { next if $store->{remove}{ $f } or $store->{exclude}{ $f }; @@ -135,8 +144,8 @@ sub unimport { =head2 get_class_store -This returns a reference to a hash in your package containing information -about function names included and excluded from removal. +This returns a reference to a hash in a passed package containing +information about function names included and excluded from removal. =cut @@ -158,14 +167,30 @@ sub get_functions { my ($pragma, $class) = @_; return { - map { @$_ } - grep { *{ $_->[1] }{CODE} } - map { [$_, qualify_to_ref( $_, $class )] } - grep { $_ !~ /::$/ } - do { no strict 'refs'; keys %{ "${class}::" } } + map { @$_ } # key => value + grep { *{ $_->[1] }{CODE} } # only functions + map { [$_, qualify_to_ref( $_, $class )] } # get globref + grep { $_ !~ /::$/ } # no packages + do { no strict 'refs'; keys %{ "${class}::" } } # symbol entries }; } +=head1 IMPLEMENTATION DETAILS + +This module works through the effect that a + + delete $SomePackage::{foo}; + +will remove the C symbol from C<$SomePackage> for run time lookups +(e.g., method calls) but will leave the entry alive to be called by +already resolved names in the package itself. + +A test file has been added to the perl core to ensure that this behaviour +will be stable in future releases. + +Just for completeness sake, if you want to remove the symbol completely, +use C instead. + =head1 SEE ALSO L