You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by mm...@apache.org on 2011/05/05 16:33:36 UTC
svn commit: r1099823 - in /spamassassin/trunk: lib/Mail/SpamAssassin/Conf.pm
lib/Mail/SpamAssassin/Conf/Parser.pm lib/Mail/SpamAssassin/Plugin/Test.pm
t/if_can.t
Author: mmartinec
Date: Thu May 5 14:33:35 2011
New Revision: 1099823
URL: http://svn.apache.org/viewvc?rev=1099823&view=rev
Log:
Bug 6581: Add a rules conditional function has(), similar to can()
Modified:
spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm
spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Test.pm
spamassassin/trunk/t/if_can.t
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm?rev=1099823&r1=1099822&r2=1099823&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf.pm Thu May 5 14:33:35 2011
@@ -3595,12 +3595,24 @@ C<3.004080>.
This is a function call that returns C<1> if the plugin named
C<Name::Of::Plugin> is loaded, or C<undef> otherwise.
-=item can(Name::Of::Package::function_name)
+=item has(Name::Of::Package::function_name)
This is a function call that returns C<1> if the perl package named
C<Name::Of::Package> includes a function called C<function_name>, or C<undef>
otherwise. Note that packages can be SpamAssassin plugins or built-in classes,
-there's no difference in this respect.
+there's no difference in this respect. Internally this invokes UNIVERSAL::can.
+
+=item can(Name::Of::Package::function_name)
+
+This is a function call that returns C<1> if the perl package named
+C<Name::Of::Package> includes a function called C<function_name>
+B<and> that function returns a true value when called with no arguments,
+otherwise C<undef> is returned.
+
+Is similar to C<has>, except that it also calls the named function,
+testing its return value (unlike the perl function UNIVERSAL::can).
+This makes it possible for a 'feature' function to determine its result
+value at run time.
=back
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm?rev=1099823&r1=1099822&r2=1099823&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Conf/Parser.pm Thu May 5 14:33:35 2011
@@ -497,12 +497,16 @@ sub handle_conditional {
$eval .= $u . " ";
}
elsif ($token eq 'plugin') {
- # replace with method call
- $eval .= "\$self->cond_clause_plugin_loaded";
+ # replace with a method call
+ $eval .= '$self->cond_clause_plugin_loaded';
}
elsif ($token eq 'can') {
- # replace with method call
- $eval .= "\$self->cond_clause_can";
+ # replace with a method call
+ $eval .= '$self->cond_clause_can';
+ }
+ elsif ($token eq 'has') {
+ # replace with a method call
+ $eval .= '$self->cond_clause_has';
}
elsif ($token eq 'version') {
$eval .= $Mail::SpamAssassin::VERSION." ";
@@ -544,16 +548,31 @@ sub cond_clause_plugin_loaded {
sub cond_clause_can {
my ($self, $method) = @_;
+ $self->cond_clause_can_or_has('can', $method);
+}
+
+sub cond_clause_has {
+ my ($self, $method) = @_;
+ $self->cond_clause_can_or_has('has', $method);
+}
+
+sub cond_clause_can_or_has {
+ my ($self, $fn_name, $method) = @_;
local($1,$2);
- if ($method =~ /^(.*)::([^:]+)$/) {
+ if (!defined $method) {
+ $self->lint_warn("bad 'if' line, no argument to $fn_name(), ".
+ "in \"$self->{currentfile}\"", undef);
+ } elsif ($method =~ /^(.*)::([^:]+)$/) {
no strict "refs";
my($module, $meth) = ($1, $2);
- return UNIVERSAL::can($module,$meth) && &{$method}();
+ return 1 if UNIVERSAL::can($module,$meth) &&
+ ( $fn_name eq 'has' || &{$method}() );
} else {
- $self->lint_warn("bad 'if' line, cannot find '::' in can($method), ".
- "in \"$self->{currentfile}\"", undef);
+ $self->lint_warn("bad 'if' line, cannot find '::' in $fn_name($method), ".
+ "in \"$self->{currentfile}\"", undef);
}
+ return undef;
}
# Let's do some linting here ...
Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Test.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Test.pm?rev=1099823&r1=1099822&r2=1099823&view=diff
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Test.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/Test.pm Thu May 5 14:33:35 2011
@@ -69,4 +69,7 @@ sub check_test_plugin {
return 1;
}
+sub test_feature_xxxx_false { undef }
+sub test_feature_xxxx_true { 1 }
+
1;
Modified: spamassassin/trunk/t/if_can.t
URL: http://svn.apache.org/viewvc/spamassassin/trunk/t/if_can.t?rev=1099823&r1=1099822&r2=1099823&view=diff
==============================================================================
--- spamassassin/trunk/t/if_can.t (original)
+++ spamassassin/trunk/t/if_can.t Thu May 5 14:33:35 2011
@@ -2,33 +2,67 @@
use lib '.'; use lib 't';
use SATest; sa_t_init("if_can");
-use Test; BEGIN { plan tests => 5 };
+use Test; BEGIN { plan tests => 13 };
# ---------------------------------------------------------------------------
%patterns = (
q{ GTUBE }, 'gtube',
- q{ SHOULD_BE_CALLED }, 'should_be_called',
+ q{ SHOULD_BE_CALLED1 }, 'should_be_called1',
+ q{ SHOULD_BE_CALLED2 }, 'should_be_called2',
+ q{ SHOULD_BE_CALLED3 }, 'should_be_called3',
+ q{ SHOULD_BE_CALLED4 }, 'should_be_called4',
+ q{ SHOULD_BE_CALLED5 }, 'should_be_called5',
+ q{ SHOULD_BE_CALLED6 }, 'should_be_called6',
+ q{ SHOULD_BE_CALLED7 }, 'should_be_called7',
);
%anti_patterns = (
q{ SHOULD_NOT_BE_CALLED1 }, 'should_not_be_called1',
q{ SHOULD_NOT_BE_CALLED2 }, 'should_not_be_called2',
+ q{ SHOULD_NOT_BE_CALLED3 }, 'should_not_be_called3',
+ q{ SHOULD_NOT_BE_CALLED4 }, 'should_not_be_called4',
);
tstlocalrules (q{
loadplugin Mail::SpamAssassin::Plugin::Test
- if !can(Mail::SpamAssassin::Plugin::Test::check_test_plugin)
+
+ if (has(Mail::SpamAssassin::Plugin::Test::check_test_plugin))
+ body SHOULD_BE_CALLED1 /./
+ endif
+ if (has(Mail::SpamAssassin::Plugin::Test::test_feature_xxxx_true))
+ body SHOULD_BE_CALLED2 /./
+ endif
+ if (has(Mail::SpamAssassin::Plugin::Test::test_feature_xxxx_false))
+ body SHOULD_BE_CALLED3 /./
+ endif
+ if (can(Mail::SpamAssassin::Plugin::Test::test_feature_xxxx_true))
+ body SHOULD_BE_CALLED4 /./
+ endif
+ if (!can(Mail::SpamAssassin::Plugin::Test::test_feature_xxxx_false))
+ body SHOULD_BE_CALLED5 /./
+ endif
+ if (!has(Mail::SpamAssassin::Plugin::Test::test_feature_xxxx_nosuch))
+ body SHOULD_BE_CALLED6 /./
+ endif
+ if (!can(Mail::SpamAssassin::Plugin::Test::test_feature_xxxx_nosuch))
+ body SHOULD_BE_CALLED7 /./
+ endif
+
+ if !has(Mail::SpamAssassin::Plugin::Test::check_test_plugin)
body SHOULD_NOT_BE_CALLED1 /./
endif
- if (can(Mail::SpamAssassin::Plugin::Test::non_existent_method))
+ if (has(Mail::SpamAssassin::Plugin::Test::non_existent_method))
body SHOULD_NOT_BE_CALLED2 /./
endif
- if (can(Mail::SpamAssassin::Plugin::Test::check_test_plugin))
- body SHOULD_BE_CALLED /./
+ if (can(Mail::SpamAssassin::Plugin::Test::non_existent_method))
+ body SHOULD_NOT_BE_CALLED3 /./
+ endif
+ if (can(Mail::SpamAssassin::Plugin::Test::test_feature_xxxx_false))
+ body SHOULD_NOT_BE_CALLED4 /./
endif
});