view release on metacpan or search on metacpan
lib/Badger/Base.pm view on Meta::CPAN
#-----------------------------------------------------------------------
# generate not_implemented() and todo() methods
#-----------------------------------------------------------------------
class->methods(
map {
my $name = $_;
$name => sub {
my $self = shift;
my $ref = ref $self || $self;
my ($pkg, $file, $line, $sub) = caller(0);
$sub = (caller(1))[3]; # subroutine the caller was called from
$sub =~ s/(.*):://;
my $msg = @_ ? join(BLANK, SPACE, @_) : BLANK;
return $self->error_msg( $name => "$sub()$msg", "for $ref in $file at line $line" );
};
}
qw( not_implemented todo )
);
#-----------------------------------------------------------------------
lib/Badger/Class.pm view on Meta::CPAN
# Badger::Class and each of its subclasses have their own metaclass
# table mapping class names to objects.
my $METACLASSES = { };
{
# class/package name - define this up-front so we can use it below
sub CLASS {
# first argument is object or class name, otherwise return caller
@_ ? (ref $_[0] || $_[0])
: (caller())[0];
}
# Sorry if this messes with your head. We want class() and classes()
# methods that create Badger::Class objects. However, we also want
# Badger::Class to be subclassable (e.g. Badger::Factory::Class), where
# class() and classes() return the subclass objects instead of the usual
# Badger::Class. So we have an UBER() class method whose job it is to
# create the class() and classes() methods for the relevant metaclass
sub UBER {
lib/Badger/Class.pm view on Meta::CPAN
# variable each time the closure is called. Ho hum.
my $class;
# The class() subroutine is used to fetch/create a Badger::Class
# object for a package name. The first argument is the class name,
# or the caller's package if undefined and we look it up in $CLASSES.
# If we get a second argument then we're being asked to lookup an
# entry for a subclass of Badger::Class, e.g. Badger::Factory::Class,
# so we first lookup the correct $METACLASS table.
my $class_sub = sub {
$class = @_ ? shift : (caller())[0];
$class = ref $class || $class;
return @_
? $METACLASSES->{ $_[0] }->{ $class } ||= $_[0]->new($class)
: $CLASSES->{ $class } ||= $pkg->new($class);
};
# The classes() method returns a list of Badger::Class objects for
# each class in the inheritance chain, starting with the object
# itself, followed by each base class, their base classes, and so on.
# As with class(), we use a generator to create a closure for the
# subroutine to allow the the class object name to be parameterised.
my $classes_sub = sub {
$class = shift || (caller())[0];
$class_sub->($class)->heritage;
};
no strict REFS;
no warnings 'redefine';
*{ $pkg.PKG.'CLASS' } = \&CLASS;
*{ $pkg.PKG.'class' } = $class_sub;
*{ $pkg.PKG.'bclass' } = $class_sub; # plan B
*{ $pkg.PKG.'classes' } = $classes_sub;
*{ $pkg.PKG.'_autoload' } = \&_autoload;
lib/Badger/Class.pm view on Meta::CPAN
sub all_vars {
my ($self, $name) = @_;
my $pkg = $self->{ name };
my ($value, @values);
no strict REFS;
no warnings ONCE;
# remove any leading '$'
$name =~ s/^\$//;
# _debug("all_vars() caller: ", join(', ', caller()), "\n");
foreach my $pkg ($self->heritage) {
_debug("looking for $name in ", $pkg || "UNDEF", "\n") if DEBUG;
push(@values, $value)
if defined ($value = ${ $pkg.PKG.$name });
_debug("got: $value\n") if DEBUG && $value;
}
return wantarray ? @values : \@values;
lib/Badger/Class.pm view on Meta::CPAN
return \%merged;
}
sub hash_value {
my ($self, $name, $item, $default) = @_;
# remove any leading '$'
$name =~ s/^\$//;
# _debug("hash_value() caller: ", join(', ', caller()), "\n");
foreach my $hash ($self->all_vars($name)) {
next unless ref $hash eq HASH;
return $hash->{ $item }
if defined $hash->{ $item };
}
return $default;
}
lib/Badger/Class/Methods.pm view on Meta::CPAN
my ($name) = ($AUTOLOAD =~ /([^:]+)$/ );
return if $name eq 'DESTROY';
if (my $method = $this->can($name, @args)) {
my $that = class($this);
$class->debug("$class installing $name method in $that") if DEBUG;
$that->method( $name => $method );
return $method->($this, @args);
}
# Hmmm... what if $this isn't a subclass of Badger::Base?
return $this->error_msg( bad_method => $name, ref $this, (caller())[1,2] );
}
);
$class->debug("installed AUTOLOAD and can() in $target") if DEBUG;
}
sub args {
my $class = shift;
my $target = shift;
my $methods = @_ == 1 ? shift : [ @_ ];
lib/Badger/Debug.pm view on Meta::CPAN
}
return $debug;
}
sub debug {
my $self = shift;
my $msg = join('', @_),
my $class = ref $self || $self;
my $format = $CALLER_AT->{ format } || $FORMAT;
my ($pkg, $file, $line) = caller($CALLER_UP);
my (undef, undef, undef, $sub) = caller($CALLER_UP + 1);
if (defined $sub) {
$sub =~ s/.*?([^:]+)$/::$1()/;
}
else {
$sub = '';
}
my $where = ($class eq $pkg)
? $class . $sub
: $pkg . $sub . " ($class)";
lib/Badger/Debug.pm view on Meta::CPAN
sub debug_at {
my $self = shift;
local $CALLER_AT = shift;
local $CALLER_UP = 1;
$self->debug(@_);
}
sub debug_caller {
my $self = shift;
my ($pkg, $file, $line, $sub) = caller(1);
my $msg = "$sub called from ";
($pkg, undef, undef, $sub) = caller(2);
$msg .= "$sub in $file at line $line\n";
$self->debug($msg);
}
sub debug_callers {
my $self = shift;
my $msg = '';
my $i = 1;
while (1) {
my @info = caller($i);
last unless @info;
my ($pkg, $file, $line, $sub) = @info;
$msg .= sprintf(
"%4s: Called from %s in %s at line %s\n",
'#' . $i++, $sub, $file, $line
);
}
$self->debug($msg);
}
lib/Badger/Debug.pm view on Meta::CPAN
# enable_colour()
#
# Export hook which gets called when the Badger::Debug module is
# used with the 'colour' or 'color' option. It redefines the formats
# for $Badger::Base::DEBUG_FORMAT and $Badger::Exception::FORMAT
# to display in glorious ANSI technicolor.
#-----------------------------------------------------------------------
sub enable_colour {
my ($class, $target, $symbol) = @_;
$target ||= (caller())[0];
$symbol ||= 'colour';
print bold green "Enabling debug in $symbol from $target\n";
# colour the debug format
$MESSAGE = cyan($PROMPT) . yellow('%s');
$FORMAT
= cyan('[<where> line <line>]')
. "\n<msg>";
lib/Badger/Debug.pm view on Meta::CPAN
use Badger::Debug 'colour';
Debugging messages will then appear in colour (on a terminal supporting
ANSI escape sequences). See the L<Badger::Test> module for an example
of this in use.
=head2 :debug
Imports all of the L<debug()>, L<debugging()>, L<debug_up()>,
L<debug_caller()>, L<debug_callers> and L<debug_args()> methods.
=head2 :dump
Imports all of the L<dump()>, L<dump_ref()>, L<dump_hash()>, L<dump_list()>,
L<dump_text()>, L<dump_data()> and L<dump_data_inline()> methods.
=head1 DEBUGGING METHODS
=head2 debug($msg1, $msg2, ...)
lib/Badger/Debug.pm view on Meta::CPAN
'Normality is resumed'
);
You can also specify a custom format in the C<$info> hash array.
$at->debug_at(
{ format => '<msg> at line <line> of <file>' },
'Normality is resumed'
);
=head2 debug_caller()
Prints debugging information about the current caller.
sub wibble {
my $self = shift;
$self->debug_caller;
}
=head2 debug_callers()
lib/Badger/Exception.pm view on Meta::CPAN
sub throw {
my $self = shift;
# save relevant information from caller stack for enhanced debugging,
# but only the first time the exception is thrown
if ($self->{ trace } && ! $self->{ stack }) {
my @stack;
my $i = 1;
while (1) {
my @info = caller($i++);
last unless @info;
push(@stack, \@info);
}
$self->{ stack } = \@stack;
}
die $self;
}
lib/Badger/Exception.pm view on Meta::CPAN
This method throws the exception by calling C<die()> with the exception object
as an argument. If the C<$TRACE> flag is set to a true value then the method
will first save the pertinent details from a stack backtrace into the
exception object before throwing it.
=head2 stack()
If stack tracing is enabled then this method will return a reference to a list
of information from the caller stack at the point at which the exception was
thrown. Each item in the list is a reference to a list containing the
information returned by the inbuilt C<caller()> method. See
C<perldoc -f caller> for further information.
use Badger::Exception trace => 1;
eval {
# some code that throws an exception object
$exception->throw();
};
my $catch = $@; # exception object
lib/Badger/Exporter.pm view on Meta::CPAN
#------------------------------------------------------------------------
# import/export methods:
# import(@imports)
# export($target, @exports)
#------------------------------------------------------------------------
sub import {
my $class = shift;
my $target = (caller())[0];
# enable strict and warnings in the caller - this ensures that every
# Badger module (that calls this method - which is pretty much all of
# them) has strict/warnings enabled, without having to explicitly write
# it. Thx Moose!
strict->import;
warnings->import;
# call in the heavy guns
$class->export($target, @_);
lib/Badger/Mixin.pm view on Meta::CPAN
version => 3.00,
debug => 0,
base => 'Badger::Exporter',
import => 'class',
constants => 'PKG REFS ONCE ARRAY DELIMITER',
words => 'EXPORT_TAGS MIXINS';
sub mixin {
my $self = shift;
my $target = shift || (caller())[0];
my $class = $self->class;
my $mixins = $class->list_vars(MIXINS);
$self->debug("mixinto($target): ", $self->dump_data($mixins), "\n") if $DEBUG;
$self->export($target, $mixins);
}
sub mixins {
my $self = shift;
my $syms = @_ == 1 ? shift : [ @_ ];
my $class = $self->class;
lib/Badger/Test/Manager.pm view on Meta::CPAN
}
}
sub test_msg {
my $self = shift;
print $self->message(@_);
}
sub test_name ($) {
my $self = shift->prototype;
my ($pkg, $file, $line) = caller(2);
$self->message( name => $self->{ count }, $file, $line );
}
sub different {
my ($self, $expect, $result) = @_;
my ($pad_exp, $pad_res) = ($expect, $result);
for ($pad_exp, $pad_res) {
s/\n/\n# |/g;
}
my $msg = $self->message( not_eq => $pad_exp, $pad_res );
lib/Badger/Utils.pm view on Meta::CPAN
sub self_params {
my @args = @_;
local $SIG{__WARN__} = sub {
odd_params(@args);
} if DEBUG;
(shift, @_ && ref $_[0] eq HASH ? shift : { @_ });
}
sub odd_params {
my $method = (caller(2))[3];
$WARN->(
"$method() called with an odd number of arguments: ",
join(', ', map { defined $_ ? $_ : '<undef>' } @_),
"\n"
);
my $i = 3;
while (1) {
my @info = caller($i);
last unless @info;
my ($pkg, $file, $line, $sub) = @info;
$WARN->(
sprintf(
"%4s: Called from %s in %s at line %s\n",
'#' . ($i++ - 2), $sub, $file, $line
)
);
}
}
t/core/lib/My/Mixin/Bar.pm view on Meta::CPAN
#-----------------------------------------------------------------------
# generate not_implemented() and todo() methods
#-----------------------------------------------------------------------
class->methods(
map {
my $name = $_;
$name => sub {
my $self = shift;
my $ref = ref $self || $self;
my ($pkg, $file, $line, $sub) = caller(0);
$sub = (caller(1))[3]; # subroutine the caller was called from
$sub =~ s/(.*):://;
my $msg = @_ ? join(BLANK, SPACE, @_) : BLANK;
return $self->error_msg( $name => "$sub()$msg", "for $ref in $file at line $line" );
};
}
qw( not_implemented todo )
);
1;