Hello community,
here is the log from the commit of package perl-Mojolicious for
openSUSE:Factory checked in at 2019-07-17 14:26:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Mojolicious (Old)
and /work/SRC/openSUSE:Factory/.perl-Mojolicious.new.1887 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Mojolicious"
Wed Jul 17 14:26:54 2019 rev:112 rq:715697 version:8.21
Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Mojolicious/perl-Mojolicious.changes
2019-06-30 10:22:23.883703782 +0200
+++
/work/SRC/openSUSE:Factory/.perl-Mojolicious.new.1887/perl-Mojolicious.changes
2019-07-17 14:26:55.595407112 +0200
@@ -1,0 +2,30 @@
+Mon Jul 15 16:40:28 UTC 2019 - Oliver Kurz <[email protected]>
+
+- updated to 8.21
+ see /usr/share/doc/packages/perl-Mojolicious/Changes
+
+ 8.21 2019-07-13
+ - Undeprecated Mojo::Exception::verbose.
+ - Added support for MOJO_EXCEPTION_VERBOSE environment variable.
+ - Improved built in templates to use the same stack trace format as
+ Mojo::Exception.
+
+ 8.20 2019-07-08
+ - Improved check function in Mojo::Exception to match regular expressions
+ against stringified exception objects too.
+ - Improved num check in Mojolicious::Validator to accept negative numbers.
+ (kiwiroy)
+
+ 8.19 2019-07-07
+ - Deprecated Mojo::Exception::verbose.
+ - Added EXPERIMENTAL check and raise functions to Mojo::Exception.
+ - Added -f option to generate plugin command.
+ - Improved inspect method in Mojo::Exception to be safe to call more than
+ once.
+ - Fixed various stack trace bugs in Mojo::Exception, so your error messages
+ and stack traces can look slightly different than before.
+ - Fixed bugs in reply->exception helper that could result in exceptions
+ without error message.
+ - Fixed daemonize exception handling in Mojo::Server. (skaji)
+
+-------------------------------------------------------------------
Old:
----
Mojolicious-8.18.tar.gz
New:
----
Mojolicious-8.21.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ perl-Mojolicious.spec ++++++
--- /var/tmp/diff_new_pack.yUPl9y/_old 2019-07-17 14:26:56.447404465 +0200
+++ /var/tmp/diff_new_pack.yUPl9y/_new 2019-07-17 14:26:56.451404452 +0200
@@ -17,7 +17,7 @@
Name: perl-Mojolicious
-Version: 8.18
+Version: 8.21
Release: 0
%define cpan_name Mojolicious
Summary: Real-time web framework
++++++ Mojolicious-8.18.tar.gz -> Mojolicious-8.21.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/Changes new/Mojolicious-8.21/Changes
--- old/Mojolicious-8.18/Changes 2019-06-28 23:19:12.000000000 +0200
+++ new/Mojolicious-8.21/Changes 2019-07-13 21:37:00.000000000 +0200
@@ -1,4 +1,28 @@
+8.21 2019-07-13
+ - Undeprecated Mojo::Exception::verbose.
+ - Added support for MOJO_EXCEPTION_VERBOSE environment variable.
+ - Improved built in templates to use the same stack trace format as
+ Mojo::Exception.
+
+8.20 2019-07-08
+ - Improved check function in Mojo::Exception to match regular expressions
+ against stringified exception objects too.
+ - Improved num check in Mojolicious::Validator to accept negative numbers.
+ (kiwiroy)
+
+8.19 2019-07-07
+ - Deprecated Mojo::Exception::verbose.
+ - Added EXPERIMENTAL check and raise functions to Mojo::Exception.
+ - Added -f option to generate plugin command.
+ - Improved inspect method in Mojo::Exception to be safe to call more than
+ once.
+ - Fixed various stack trace bugs in Mojo::Exception, so your error messages
+ and stack traces can look slightly different than before.
+ - Fixed bugs in reply->exception helper that could result in exceptions
+ without error message.
+ - Fixed daemonize exception handling in Mojo::Server. (skaji)
+
8.18 2019-06-28
- Welcome to the Mojolicious core team CandyAngel, Christopher Rasch-Olsen
Raa and Dan Book.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/META.json
new/Mojolicious-8.21/META.json
--- old/Mojolicious-8.18/META.json 2019-06-28 23:28:50.000000000 +0200
+++ new/Mojolicious-8.21/META.json 2019-07-14 19:08:42.000000000 +0200
@@ -19,6 +19,10 @@
"inc",
"examples",
"t"
+ ],
+ "package" : [
+ "Mojo::Exception::_Guard",
+ "Mojo::Server::PSGI::_IO"
]
},
"prereqs" : {
@@ -58,6 +62,6 @@
},
"x_IRC" : "irc://irc.freenode.net/#mojo"
},
- "version" : "8.18",
- "x_serialization_backend" : "JSON::PP version 4.02"
+ "version" : "8.21",
+ "x_serialization_backend" : "JSON::PP version 4.04"
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/META.yml
new/Mojolicious-8.21/META.yml
--- old/Mojolicious-8.18/META.yml 2019-06-28 23:28:50.000000000 +0200
+++ new/Mojolicious-8.21/META.yml 2019-07-14 19:08:42.000000000 +0200
@@ -19,6 +19,9 @@
- inc
- examples
- t
+ package:
+ - Mojo::Exception::_Guard
+ - Mojo::Server::PSGI::_IO
requires:
IO::Socket::IP: '0.37'
JSON::PP: '2.27103'
@@ -31,5 +34,5 @@
homepage: https://mojolicious.org
license: http://www.opensource.org/licenses/artistic-license-2.0
repository: https://github.com/mojolicious/mojo.git
-version: '8.18'
+version: '8.21'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/Makefile.PL
new/Mojolicious-8.21/Makefile.PL
--- old/Mojolicious-8.18/Makefile.PL 2018-12-10 21:34:06.000000000 +0100
+++ new/Mojolicious-8.21/Makefile.PL 2019-07-09 22:57:59.000000000 +0200
@@ -18,9 +18,12 @@
META_MERGE => {
dynamic_config => 0,
'meta-spec' => {version => 2},
- no_index => {directory => ['examples', 't']},
- prereqs => {runtime => {requires => {perl => '5.010001'}}},
- resources => {
+ no_index => {
+ directory => [qw(examples t)],
+ package => [qw(Mojo::Exception::_Guard Mojo::Server::PSGI::_IO)],
+ },
+ prereqs => {runtime => {requires => {perl => '5.010001'}}},
+ resources => {
bugtracker => {web => 'https://github.com/mojolicious/mojo/issues'},
homepage => 'https://mojolicious.org',
license =>
['http://www.opensource.org/licenses/artistic-license-2.0'],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/README.md
new/Mojolicious-8.21/README.md
--- old/Mojolicious-8.18/README.md 2018-10-22 17:34:04.000000000 +0200
+++ new/Mojolicious-8.21/README.md 2019-07-09 18:33:40.000000000 +0200
@@ -7,13 +7,19 @@
# [](https://travis-ci.com/mojoliocus/mojo)
[](https://ci.appveyor.com/project/kraih73737/mojo)
- Back in the early days of the web, many people learned Perl because of a
- wonderful Perl library called [CGI](https://metacpan.org/module/CGI). It was
- simple enough to get started without knowing much about the language and
- powerful enough to keep you going, learning by doing was much fun. While
- most of the techniques used are outdated now, the idea behind it is not.
- Mojolicious is a new endeavor to implement this idea using bleeding edge
- technologies.
+ Mojolicious is a fresh take on Perl web development, based on years of
+ experience developing the Catalyst framework, and utilizing the latest
+ web standards and technologies. You can get started with your project
+ quickly, with a framework that grows with your needs.
+
+ The Mojo stack provides a consistent set of components that can be used in
+ any project. The guides cover most aspects of using the framework and the
+ components have comprehensive reference documentation. Mojolicious is a
+ real-time web framework, which allows a new class of web applications
+ using WebSockets and having long-running requests without blocking.
+
+ Join us now, and be a part of a friendly and knowledgeable community of
+ developers!
## Features
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Content/MultiPart.pm
new/Mojolicious-8.21/lib/Mojo/Content/MultiPart.pm
--- old/Mojolicious-8.18/lib/Mojo/Content/MultiPart.pm 2019-06-21
22:48:51.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojo/Content/MultiPart.pm 2019-07-09
20:50:53.000000000 +0200
@@ -304,8 +304,8 @@
my $multi
= Mojo::Content::MultiPart->new({parts => [Mojo::Content::Single->new]});
-Construct a new L<Mojo::Content::MultiPart> object and subscribe to L</"read">
-event with default content parser.
+Construct a new L<Mojo::Content::MultiPart> object and subscribe to event
+L<Mojo::Content/"read"> with default content parser.
=head1 SEE ALSO
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Content/Single.pm
new/Mojolicious-8.21/lib/Mojo/Content/Single.pm
--- old/Mojolicious-8.18/lib/Mojo/Content/Single.pm 2019-06-21
22:48:51.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojo/Content/Single.pm 2019-07-09
20:50:43.000000000 +0200
@@ -152,8 +152,8 @@
my $single = Mojo::Content::Single->new(asset => Mojo::Asset::File->new);
my $single = Mojo::Content::Single->new({asset => Mojo::Asset::File->new});
-Construct a new L<Mojo::Content::Single> object and subscribe to L</"read">
-event with default content parser.
+Construct a new L<Mojo::Content::Single> object and subscribe to event
+L<Mojo::Content/"read"> with default content parser.
=head2 parse
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Cookie/Response.pm
new/Mojolicious-8.21/lib/Mojo/Cookie/Response.pm
--- old/Mojolicious-8.18/lib/Mojo/Cookie/Response.pm 2019-06-21
22:48:57.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojo/Cookie/Response.pm 2019-07-07
14:10:25.000000000 +0200
@@ -139,7 +139,7 @@
my $samesite = $cookie->samesite;
$cookie = $cookie->samesite('Lax');
-SameSite value. Note that this attribute is EXPERIMENTAL because even though
+SameSite value. Note that this attribute is B<EXPERIMENTAL> because even though
most commonly used browsers support the feature, there is no specification yet
besides
L<this draft|https://tools.ietf.org/html/draft-west-first-party-cookies-07>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/DOM/CSS.pm
new/Mojolicious-8.21/lib/Mojo/DOM/CSS.pm
--- old/Mojolicious-8.18/lib/Mojo/DOM/CSS.pm 2019-06-21 22:48:57.000000000
+0200
+++ new/Mojolicious-8.21/lib/Mojo/DOM/CSS.pm 2019-07-07 14:10:59.000000000
+0200
@@ -387,7 +387,7 @@
An C<E> element whose C<foo> attribute value is exactly equal to any
(ASCII-range) case-permutation of C<bar>. Note that this selector is
-EXPERIMENTAL and might change without warning!
+B<EXPERIMENTAL> and might change without warning!
my $case_insensitive = $css->select('input[type="hidden" i]');
my $case_insensitive = $css->select('input[type=hidden i]');
@@ -555,7 +555,7 @@
=head2 E:not(s1, s2)
An C<E> element that does not match either compound selector C<s1> or compound
-selector C<s2>. Note that support for compound selectors is EXPERIMENTAL and
+selector C<s2>. Note that support for compound selectors is B<EXPERIMENTAL> and
might change without warning!
my $others = $css->select('div p:not(:first-child, :last-child)');
@@ -567,7 +567,8 @@
=head2 E:matches(s1, s2)
An C<E> element that matches compound selector C<s1> and/or compound selector
-C<s2>. Note that this selector is EXPERIMENTAL and might change without
warning!
+C<s2>. Note that this selector is B<EXPERIMENTAL> and might change without
+warning!
my $headers = $css->select(':matches(section, article, aside, nav) h1');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/DynamicMethods.pm
new/Mojolicious-8.21/lib/Mojo/DynamicMethods.pm
--- old/Mojolicious-8.18/lib/Mojo/DynamicMethods.pm 2019-06-21
22:48:50.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojo/DynamicMethods.pm 2019-07-07
14:11:08.000000000 +0200
@@ -95,7 +95,7 @@
};
}
-Note that this module is EXPERIMENTAL and might change without warning!
+Note that this module is B<EXPERIMENTAL> and might change without warning!
=head1 FUNCTIONS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Exception.pm
new/Mojolicious-8.21/lib/Mojo/Exception.pm
--- old/Mojolicious-8.18/lib/Mojo/Exception.pm 2019-06-21 22:48:46.000000000
+0200
+++ new/Mojolicious-8.21/lib/Mojo/Exception.pm 2019-07-13 21:17:39.000000000
+0200
@@ -2,19 +2,58 @@
use Mojo::Base -base;
use overload bool => sub {1}, '""' => sub { shift->to_string }, fallback => 1;
+use Exporter 'import';
use Mojo::Util 'decode';
+use Scalar::Util 'blessed';
has [qw(frames line lines_after lines_before)] => sub { [] };
has message => 'Exception!';
-has 'verbose';
+has verbose => sub { $ENV{MOJO_EXCEPTION_VERBOSE} };
+
+our @EXPORT_OK = qw(check raise);
+
+sub check {
+ my ($err, @spec) = @_ % 2 ? @_ : ($@, @_);
+
+ # Finally (search backwards since it is usually at the end)
+ my $guard;
+ for (my $i = $#spec - 1; $i >= 0; $i -= 2) {
+ ($guard = Mojo::Exception::_Guard->new(finally => $spec[$i + 1])) and last
+ if $spec[$i] eq 'finally';
+ }
+
+ return undef unless $err;
+
+ my ($default, $handler);
+ my ($is_obj, $str) = (!!blessed($err), "$err");
+CHECK: for (my $i = 0; $i < @spec; $i += 2) {
+ my ($checks, $cb) = @spec[$i, $i + 1];
+
+ ($default = $cb) and next if $checks eq 'default';
+
+ for my $c (ref $checks eq 'ARRAY' ? @$checks : $checks) {
+ my $is_re = !!ref $c;
+ ($handler = $cb) and last CHECK if $is_obj && !$is_re && $err->isa($c);
+ ($handler = $cb) and last CHECK if $is_re && $str =~ $c;
+ }
+ }
+
+ # Rethrow if no handler could be found
+ die $err unless $handler ||= $default;
+ $handler->($_) for $err;
+
+ return 1;
+}
sub inspect {
my ($self, @sources) = @_;
+ return $self if @{$self->line};
+
# Extract file and line from message
my @files;
- my $msg = $self->lines_before([])->line([])->lines_after([])->message;
- while ($msg =~ /at\s+(.+?)\s+line\s+(\d+)/g) { unshift @files, [$1, $2] }
+ my $msg = $self->message;
+ unshift @files, [$1, $2] while $msg =~ /at\s+(.+?)\s+line\s+(\d+)/g;
# Extract file and line from stack trace
if (my $zero = $self->frames->[0]) { push @files, [$zero->[1], $zero->[2]] }
@@ -32,24 +71,50 @@
return $self;
}
-sub new { @_ > 1 ? shift->SUPER::new(message => shift) : shift->SUPER::new }
+sub new {
+ defined $_[1] ? shift->SUPER::new(message => shift) : shift->SUPER::new;
+}
+
+sub raise {
+ my ($class, $err) = @_ > 1 ? (@_) : (__PACKAGE__, shift);
+
+ if (!$class->can('new')) {
+ die $@ unless eval "package $class; use Mojo::Base 'Mojo::Exception'; 1";
+ }
+ elsif (!$class->isa(__PACKAGE__)) {
+ die "$class is not a Mojo::Exception subclass";
+ }
+
+ CORE::die $class->new($err)->trace;
+}
sub to_string {
my $self = shift;
my $str = $self->message;
- return $str unless $self->verbose;
-
$str .= "\n" unless $str =~ /\n$/;
- $str .= $_->[0] . ': ' . $_->[1] . "\n" for @{$self->lines_before};
- $str .= $self->line->[0] . ': ' . $self->line->[1] . "\n" if
$self->line->[0];
- $str .= $_->[0] . ': ' . $_->[1] . "\n" for @{$self->lines_after};
- $str .= "$_->[1]:$_->[2] ($_->[0])\n" for @{$self->frames};
+
+ my $line = $self->line;
+ if (@$line) {
+ $str .= "Context:\n";
+ $str .= " $_->[0]: $_->[1]\n" for @{$self->lines_before};
+ $str .= " $line->[0]: $line->[1]\n";
+ $str .= " $_->[0]: $_->[1]\n" for @{$self->lines_after};
+ }
+
+ my $frames = $self->frames;
+ if (my $max = @$frames) {
+ $str .= "Traceback (most recent call first):\n";
+ my $offset = $self->verbose ? $#$frames : $#$frames <= 4 ? $#$frames : 4;
+ $str .= qq{ File "$_->[1]", line $_->[2], in "$_->[0]"\n}
+ for @$frames[0 .. $offset];
+ $str .= " ...\n" if $max > ($offset + 1);
+ }
return $str;
}
-sub throw { CORE::die shift->new(shift)->trace(2)->inspect }
+sub throw { CORE::die shift->new(shift)->trace }
sub trace {
my ($self, $start) = (shift, shift // 1);
@@ -89,33 +154,129 @@
}
}
+package Mojo::Exception::_Guard;
+use Mojo::Base -base;
+
+sub DESTROY { shift->{finally}->() }
+
1;
=encoding utf8
=head1 NAME
-Mojo::Exception - Exceptions with context
+Mojo::Exception - Exception base class
=head1 SYNOPSIS
- use Mojo::Exception;
+ # Create exception classes
+ package MyApp::X::Foo {
+ use Mojo::Base 'Mojo::Exception';
+ }
+ package MyApp::X::Bar {
+ use Mojo::Base 'Mojo::Exception';
+ }
- # Throw exception and show stack trace
- eval { Mojo::Exception->throw('Something went wrong!') };
- say "$_->[1]:$_->[2]" for @{$@->frames};
+ # Throw exceptions and handle them gracefully
+ use Mojo::Exception 'check';
+ eval {
+ MyApp::X::Foo->throw('Something went wrong!');
+ };
+ check(
+ 'MyApp::X::Foo' => sub { say "Foo: $_" },
+ 'MyApp::X::Bar' => sub { say "Bar: $_" }
+ );
- # Customize exception
+ # Generate exception classes on demand
+ use Mojo::Exception qw(check raise);
eval {
- my $e = Mojo::Exception->new('Died at test.pl line 3.');
- die $e->trace(2)->inspect->verbose(1);
+ raise 'MyApp::X::Name', 'The name Minion is already taken';
};
- say $@;
+ check(
+ 'MyApp::X::Name' => sub { say "Name error: $_" },
+ default => sub { say "Error: $_" }
+ );
=head1 DESCRIPTION
L<Mojo::Exception> is a container for exceptions with context information.
+=head1 FUNCTIONS
+
+L<Mojo::Exception> implements the following functions, which can be imported
+individually.
+
+=head2 check
+
+ my $bool = check 'MyApp::X::Foo' => sub {...};
+ my $bool = check $err, 'MyApp::X::Foo' => sub {...};
+
+Process exceptions by dispatching them to handlers with one or more matching
+conditions. Exceptions that could not be handled will be rethrown
automatically.
+By default C<$@> will be used as exception source, so C<check> needs to be
+called right after C<eval>. Note that this function is B<EXPERIMENTAL> and
might
+change without warning!
+
+ # Handle various types of exceptions
+ eval {
+ dangerous_code();
+ };
+ check(
+ 'MyApp::X::Foo' => sub { say "Foo: $_" },
+ qr/^Could not open/ => sub { say "Open error: $_" },
+ default => sub { say "Something went wrong: $_" },
+ finally => sub { say 'Dangerous code is done' }
+ );
+
+Matching conditions can be class names for ISA checks on exception objects, or
+regular expressions to match string exceptions and stringified exception
+objects. The matching exception will be the first argument passed to the
+callback, and is also available as C<$_>.
+
+ # Catch MyApp::X::Foo object or a specific string exception
+ eval {
+ dangerous_code();
+ };
+ check(
+ 'MyApp::X::Foo' => sub { say "Foo: $_" },
+ qr/^Could not open/ => sub { say "Open error: $_" }
+ );
+
+An array reference can be used to share the same handler with multiple
+conditions, of which only one needs to match. And since exception handlers are
+just callbacks, they can also throw their own exceptions.
+
+ # Handle MyApp::X::Foo and MyApp::X::Bar the same
+ eval {
+ dangerous_code();
+ };
+ check(
+ ['MyApp::X::Foo', 'MyApp::X::Bar'] => sub { die "Foo/Bar: $_" }
+ );
+
+There are currently two keywords you can use to set special handlers. The
+C<default> handler is used when no other handler matched. And the C<finally>
+handler runs always, it does not affect normal handlers and even runs if the
+exception was rethrown or if there was no exception to be handled at all.
+
+ # Use "default" to catch everything
+ eval {
+ dangerous_code();
+ };
+ check(
+ default => sub { say "Error: $_" },
+ finally => sub { say 'Dangerous code is done' }
+ );
+
+=head2 raise
+
+ raise 'Something went wrong!';
+ raise 'MyApp::X::Foo', 'Something went wrong!';
+
+Raise a L<Mojo::Exception>, if the class does not exist yet (classes are
checked
+for a C<new> method), one is created as a L<Mojo::Exception> subclass on
demand.
+Note that this function is B<EXPERIMENTAL> and might change without warning!
+
=head1 ATTRIBUTES
L<Mojo::Exception> implements the following attributes.
@@ -164,7 +325,8 @@
my $bool = $e->verbose;
$e = $e->verbose($bool);
-Enable context information for L</"to_string">.
+Show more information with L</"to_string">, such as additional L</"frames">,
+defaults to the value of the C<MOJO_EXCEPTION_VERBOSE> environment variable.
=head1 METHODS
@@ -190,10 +352,9 @@
my $str = $e->to_string;
-Render exception.
-
- # Render exception with context
- say $e->verbose(1)->to_string;
+Render exception. Note that the output format may change as more features are
+added, only the error message at the beginning is guaranteed not to be modified
+to allow regex matching.
=head2 throw
@@ -202,7 +363,7 @@
Throw exception from the current execution context.
# Longer version
- die Mojo::Exception->new('Something went wrong!')->trace->inspect;
+ die Mojo::Exception->new('Something went wrong!')->trace;
=head2 trace
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Headers.pm
new/Mojolicious-8.21/lib/Mojo/Headers.pm
--- old/Mojolicious-8.18/lib/Mojo/Headers.pm 2019-06-28 18:11:58.000000000
+0200
+++ new/Mojolicious-8.21/lib/Mojo/Headers.pm 2019-07-07 14:11:28.000000000
+0200
@@ -412,7 +412,7 @@
$heders = $headers->dehop;
Remove hop-by-hop headers that should not be retransmitted. Note that this
-method is EXPERIMENTAL and might change without warning!
+method is B<EXPERIMENTAL> and might change without warning!
=head2 dnt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/IOLoop/Stream.pm
new/Mojolicious-8.21/lib/Mojo/IOLoop/Stream.pm
--- old/Mojolicious-8.18/lib/Mojo/IOLoop/Stream.pm 2019-06-28
18:11:58.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojo/IOLoop/Stream.pm 2019-07-07
14:11:59.000000000 +0200
@@ -244,8 +244,8 @@
$msg = $msg->high_water_mark(1024);
Maximum size of L</"write"> buffer in bytes before L</"can_write"> returns
-false, defaults to C<1048576> (1MiB). Note that this attribute is EXPERIMENTAL
-and might change without warning!
+false, defaults to C<1048576> (1MiB). Note that this attribute is
+B<EXPERIMENTAL> and might change without warning!
=head2 reactor
@@ -271,7 +271,8 @@
my $num = $stream->bytes_waiting;
Number of bytes that have been enqueued with L</"write"> and are waiting to be
-written. Note that this method is EXPERIMENTAL and might change without
warning!
+written. Note that this method is B<EXPERIMENTAL> and might change without
+warning!
=head2 bytes_written
@@ -284,7 +285,7 @@
my $bool = $stream->can_write;
Returns true if calling L</"write"> is safe. Note that this method is
-EXPERIMENTAL and might change without warning!
+B<EXPERIMENTAL> and might change without warning!
=head2 close
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Promise.pm
new/Mojolicious-8.21/lib/Mojo/Promise.pm
--- old/Mojolicious-8.18/lib/Mojo/Promise.pm 2019-06-21 22:48:47.000000000
+0200
+++ new/Mojolicious-8.21/lib/Mojo/Promise.pm 2019-07-07 14:12:31.000000000
+0200
@@ -342,7 +342,7 @@
items while optionally limiting concurrency. Returns a L<Mojo::Promise> that
collects the results in the same manner as L</all>. If any item's promise is
rejected, any remaining items which have not yet been mapped will not be. Note
-that this method is EXPERIMENTAL and might change without warning!
+that this method is B<EXPERIMENTAL> and might change without warning!
# Perform 3 requests at a time concurrently
Mojo::Promise->map({concurrency => 3}, sub { $ua->get_p($_) }, @urls)
@@ -449,8 +449,8 @@
Create a new L<Mojo::Promise> object with a timer or attach a timer to an
existing promise. The promise will be resolved after the given amount of time
in
-seconds with or without a value. Note that this method is EXPERIMENTAL and
might
-change without warning!
+seconds with or without a value. Note that this method is B<EXPERIMENTAL> and
+might change without warning!
=head2 timeout
@@ -461,7 +461,7 @@
Create a new L<Mojo::Promise> object with a timeout or attach a timeout to an
existing promise. The promise will be rejected after the given amount of time
in
seconds with a reason, which defaults to C<Promise timeout>. Note that this
-method is EXPERIMENTAL and might change without warning!
+method is B<EXPERIMENTAL> and might change without warning!
=head2 wait
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Server.pm
new/Mojolicious-8.21/lib/Mojo/Server.pm
--- old/Mojolicious-8.18/lib/Mojo/Server.pm 2019-06-21 22:48:46.000000000
+0200
+++ new/Mojolicious-8.21/lib/Mojo/Server.pm 2019-06-29 19:39:13.000000000
+0200
@@ -30,7 +30,7 @@
# Fork and kill parent
die "Can't fork: $!" unless defined(my $pid = fork);
exit 0 if $pid;
- POSIX::setsid or die "Can't start a new session: $!";
+ POSIX::setsid == -1 and die "Can't start a new session: $!";
# Close filehandles
open STDIN, '<', '/dev/null';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojo/Template.pm
new/Mojolicious-8.21/lib/Mojo/Template.pm
--- old/Mojolicious-8.18/lib/Mojo/Template.pm 2019-06-21 22:48:56.000000000
+0200
+++ new/Mojolicious-8.21/lib/Mojo/Template.pm 2019-07-09 20:05:03.000000000
+0200
@@ -146,8 +146,7 @@
unless ($compiled) {
my $code = $self->_compile->code;
monkey_patch $self->namespace, '_escape', $self->escape;
- return Mojo::Exception->new($@)->inspect($self->unparsed, $code)
- ->trace->verbose(1)
+ return Mojo::Exception->new($@)->inspect($self->unparsed, $code)->trace
unless $compiled = eval $self->_wrap($code, @_);
$self->compiled($compiled);
}
@@ -156,7 +155,7 @@
local $SIG{__DIE__} = sub {
CORE::die $_[0] if ref $_[0];
CORE::die Mojo::Exception->new(shift)
- ->trace->inspect($self->unparsed, $self->code)->verbose(1);
+ ->trace->inspect($self->unparsed, $self->code);
};
my $output;
@@ -413,14 +412,16 @@
error messages with context.
Bareword "xx" not allowed while "strict subs" in use at template line 4.
- 2: </head>
- 3: <body>
- 4: % my $i = 2; xx
- 5: %= $i * 2
- 6: </body>
- template:4 (Mojo::Template::Sandbox)
- path/to/Mojo/Template.pm:123 (Mojo::Template)
- path/to/myapp.pl:123 (main)
+ Context:
+ 2: </head>
+ 3: <body>
+ 4: % my $i = 2; xx
+ 5: %= $i * 2
+ 6: </body>
+ Traceback (most recent call first):
+ File "template", line 4, in "Mojo::Template::Sandbox"
+ File "path/to/Mojo/Template.pm", line 123, in "Mojo::Template"
+ File "path/to/myapp.pl", line 123, in "main"
=head1 ATTRIBUTES
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Mojolicious-8.18/lib/Mojolicious/Command/Author/generate/app.pm
new/Mojolicious-8.21/lib/Mojolicious/Command/Author/generate/app.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Command/Author/generate/app.pm
2019-06-21 22:49:08.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Command/Author/generate/app.pm
2019-06-29 21:18:51.000000000 +0200
@@ -9,12 +9,6 @@
sub run {
my ($self, $class) = (shift, shift || 'MyApp');
- # Prevent bad applications
- die <<EOF unless $class =~ /^[A-Z](?:\w|::)+$/;
-Your application name has to be a well formed (CamelCase) Perl module name
-like "MyApp".
-EOF
-
# Script
my $name = class_to_file $class;
$self->render_to_rel_file('mojo', "$name/script/$name", {class => $class});
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Mojolicious-8.18/lib/Mojolicious/Command/Author/generate/makefile.pm
new/Mojolicious-8.21/lib/Mojolicious/Command/Author/generate/makefile.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Command/Author/generate/makefile.pm
2019-06-21 22:49:07.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Command/Author/generate/makefile.pm
2019-06-29 21:33:56.000000000 +0200
@@ -1,8 +1,6 @@
package Mojolicious::Command::Author::generate::makefile;
use Mojo::Base 'Mojolicious::Command';
-use Mojolicious;
-
has description => 'Generate "Makefile.PL"';
has usage => sub { shift->extract_usage };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Mojolicious-8.18/lib/Mojolicious/Command/Author/generate/plugin.pm
new/Mojolicious-8.21/lib/Mojolicious/Command/Author/generate/plugin.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Command/Author/generate/plugin.pm
2019-06-21 22:49:07.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Command/Author/generate/plugin.pm
2019-06-29 21:41:03.000000000 +0200
@@ -1,20 +1,21 @@
package Mojolicious::Command::Author::generate::plugin;
use Mojo::Base 'Mojolicious::Command';
-use Mojo::Util qw(camelize class_to_path);
-use Mojolicious;
+use Mojo::Util qw(camelize class_to_path getopt);
has description => 'Generate Mojolicious plugin directory structure';
has usage => sub { shift->extract_usage };
sub run {
- my ($self, $name) = (shift, shift || 'MyPlugin');
+ my ($self, @args) = @_;
+
+ getopt \@args, 'f|full' => \(my $full);
# Class
- my $class = $name =~ /^[a-z]/ ? camelize $name : $name;
- $class = "Mojolicious::Plugin::$class";
- my $app = class_to_path $class;
- my $dir = join '-', split('::', $class);
+ my $name = $args[0] // 'MyPlugin';
+ my $class = $full ? $name : "Mojolicious::Plugin::$name";
+ my $dir = join '-', split('::', $class);
+ my $app = class_to_path $class;
$self->render_to_rel_file('class', "$dir/lib/$app",
{class => $class, name => $name});
@@ -40,8 +41,10 @@
mojo generate plugin
mojo generate plugin TestPlugin
+ mojo generate plugin -f MyApp::Plugin::AwesomeFeature
Options:
+ -f, --full Do not prepend "Mojolicious::Plugin::" to the plugin name
-h, --help Show this summary of available options
=head1 DESCRIPTION
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Mojolicious-8.18/lib/Mojolicious/Plugin/DefaultHelpers.pm
new/Mojolicious-8.21/lib/Mojolicious/Plugin/DefaultHelpers.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Plugin/DefaultHelpers.pm
2019-06-28 18:11:58.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Plugin/DefaultHelpers.pm
2019-07-07 14:13:07.000000000 +0200
@@ -96,7 +96,7 @@
my ($page, $c, $e) = @_;
my $app = $c->app;
- $app->log->error($e = _exception($e) ? $e :
Mojo::Exception->new($e)->inspect)
+ $app->log->error(($e = _is_e($e) ? $e : Mojo::Exception->new($e))->inspect)
if $page eq 'exception';
# Filtered stash snapshot
@@ -119,7 +119,6 @@
return $c;
}
-sub _exception { blessed $_[0] && $_[0]->isa('Mojo::Exception') }
sub _fallbacks {
my ($c, $options, $template, $bundled) = @_;
@@ -161,6 +160,8 @@
return $c;
}
+sub _is_e { blessed $_[0] && $_[0]->isa('Mojo::Exception') }
+
sub _is_fresh {
my ($c, %options) = @_;
return $c->app->static->is_fresh($c, \%options);
@@ -529,8 +530,8 @@
Perform non-blocking C<GET> request and forward response as efficiently as
possible, takes the same arguments as L<Mojo::UserAgent/"get"> and returns a
-L<Mojo::Promise> object. Note that this helper is EXPERIMENTAL and might change
-without warning!
+L<Mojo::Promise> object. Note that this helper is B<EXPERIMENTAL> and might
+change without warning!
# Forward with exception handling
$c->proxy->get_p('http://mojolicious.org')->catch(sub {
@@ -545,8 +546,8 @@
Perform non-blocking C<POST> request and forward response as efficiently as
possible, takes the same arguments as L<Mojo::UserAgent/"post"> and returns a
-L<Mojo::Promise> object. Note that this helper is EXPERIMENTAL and might change
-without warning!
+L<Mojo::Promise> object. Note that this helper is B<EXPERIMENTAL> and might
+change without warning!
# Forward with exception handling
$c->proxy->post_p('example.com' => form => {test => 'pass'})->catch(sub {
@@ -561,7 +562,7 @@
Perform non-blocking request for a custom L<Mojo::Transaction::HTTP> object and
forward response as efficiently as possible, returns a L<Mojo::Promise> object.
-Note that this helper is EXPERIMENTAL and might change without warning!
+Note that this helper is B<EXPERIMENTAL> and might change without warning!
# Forward with exception handling
my $tx = $c->ua->build_tx(GET => 'http://mojolicious.org');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojolicious/Renderer.pm
new/Mojolicious-8.21/lib/Mojolicious/Renderer.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Renderer.pm 2019-06-21
22:49:04.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Renderer.pm 2019-07-07
14:13:38.000000000 +0200
@@ -287,7 +287,7 @@
Try to negotiate compression for dynamically generated response content and
C<gzip> compress it automatically, defaults to false. Note that this attribute
-is EXPERIMENTAL and might change without warning!
+is B<EXPERIMENTAL> and might change without warning!
=head2 default_format
@@ -335,7 +335,7 @@
$renderer = $renderer->min_compress_size(1024);
Minimum output size in bytes required for compression to be used if enabled,
-defaults to C<860>. Note that this attribute is EXPERIMENTAL and might change
+defaults to C<860>. Note that this attribute is B<EXPERIMENTAL> and might
change
without warning!
=head2 paths
@@ -427,7 +427,7 @@
Mojolicious::Controller->new, $output, $format, $status);
Finalize dynamically generated response content and L</"compress"> it if
-possible. Note that this method is EXPERIMENTAL and might change without
+possible. Note that this method is B<EXPERIMENTAL> and might change without
warning!
=head2 template_for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojolicious/Sessions.pm
new/Mojolicious-8.21/lib/Mojolicious/Sessions.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Sessions.pm 2019-06-21
22:49:02.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Sessions.pm 2019-07-07
14:13:51.000000000 +0200
@@ -148,8 +148,8 @@
$sessions = $sessions->samesite('Strict');
Set the SameSite value on all session cookies, defaults to C<Lax>. Note that
-this attribute is EXPERIMENTAL because even though most commonly used browsers
-support the feature, there is no specification yet besides
+this attribute is B<EXPERIMENTAL> because even though most commonly used
+browsers support the feature, there is no specification yet besides
L<this draft|https://tools.ietf.org/html/draft-west-first-party-cookies-07>.
# Disable SameSite feature
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojolicious/Types.pm
new/Mojolicious-8.21/lib/Mojolicious/Types.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Types.pm 2019-06-21
22:49:06.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Types.pm 2019-07-07
14:14:09.000000000 +0200
@@ -146,7 +146,7 @@
Detect MIME type for L<Mojolicious::Controller> object unless a C<Content-Type>
response header has already been set, defaults to using the MIME type for the
C<txt> extension if no better alternative could be found. Note that this method
-is EXPERIMENTAL and might change without warning!
+is B<EXPERIMENTAL> and might change without warning!
These options are currently available:
@@ -179,7 +179,7 @@
my $type = $types->file_type('foo/bar.png');
-Get MIME type for file path. Note that this method is EXPERIMENTAL and might
+Get MIME type for file path. Note that this method is B<EXPERIMENTAL> and might
change without warning!
=head2 type
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojolicious/Validator.pm
new/Mojolicious-8.21/lib/Mojolicious/Validator.pm
--- old/Mojolicious-8.18/lib/Mojolicious/Validator.pm 2019-06-21
22:49:02.000000000 +0200
+++ new/Mojolicious-8.21/lib/Mojolicious/Validator.pm 2019-07-09
19:25:38.000000000 +0200
@@ -49,7 +49,7 @@
sub _num {
my ($v, $name, $value, $min, $max) = @_;
- return 1 if $value !~ /^[0-9]+$/;
+ return 1 if $value !~ /^-?[0-9]+$/;
return defined $min && $min > $value || defined $max && $max < $value;
}
@@ -109,11 +109,12 @@
$v = $v->num;
$v = $v->num(2, 5);
+ $v = $v->num(-3, 7);
$v = $v->num(2, undef);
$v = $v->num(undef, 5);
-String value needs to be a non-fractional number and if provided in the given
-range.
+String value needs to be a non-fractional number (positive or negative) and if
+provided in the given range.
=head2 size
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/Mojolicious-8.18/lib/Mojolicious/resources/templates/mojo/debug.html.ep
new/Mojolicious-8.21/lib/Mojolicious/resources/templates/mojo/debug.html.ep
--- old/Mojolicious-8.18/lib/Mojolicious/resources/templates/mojo/debug.html.ep
2019-01-01 19:21:42.000000000 +0100
+++ new/Mojolicious-8.21/lib/Mojolicious/resources/templates/mojo/debug.html.ep
2019-07-14 19:07:28.000000000 +0200
@@ -322,7 +322,8 @@
% for my $frame (@{$exception->frames}) {
<tr>
<td class="striped value wide">
- <pre><%= $frame->[1] . ':' . $frame->[2] %></pre>
+ <pre>File "<%= $frame->[1] %>", line <%=
+ $frame->[2] %>, in "<%= $frame->[0] %>"</pre>
</td>
</tr>
% }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/lib/Mojolicious.pm
new/Mojolicious-8.21/lib/Mojolicious.pm
--- old/Mojolicious-8.18/lib/Mojolicious.pm 2019-06-28 01:35:47.000000000
+0200
+++ new/Mojolicious-8.21/lib/Mojolicious.pm 2019-07-09 23:01:29.000000000
+0200
@@ -59,7 +59,7 @@
has validator => sub { Mojolicious::Validator->new };
our $CODENAME = 'Supervillain';
-our $VERSION = '8.18';
+our $VERSION = '8.21';
sub BUILD_DYNAMIC {
my ($class, $method, $dyn_methods) = @_;
@@ -197,10 +197,11 @@
sub startup { }
+sub _die { CORE::die ref $_[0] ? $_[0] : Mojo::Exception->new(shift)->trace }
+
sub _exception {
my ($next, $c) = @_;
- local $SIG{__DIE__}
- = sub { ref $_[0] ? CORE::die $_[0] : Mojo::Exception->throw(shift) };
+ local $SIG{__DIE__} = \&_die;
$c->helpers->reply->exception($@) unless eval { $next->(); 1 };
}
@@ -1156,6 +1157,8 @@
Simone Tampieri
+Shoichi Kaji
+
Shu Cho
Skye Shaw
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/t/mojo/exception.t
new/Mojolicious-8.21/t/mojo/exception.t
--- old/Mojolicious-8.18/t/mojo/exception.t 2019-05-31 21:28:59.000000000
+0200
+++ new/Mojolicious-8.21/t/mojo/exception.t 2019-07-13 21:17:36.000000000
+0200
@@ -1,16 +1,34 @@
use Mojo::Base -strict;
use Test::More;
-use Mojo::Exception;
+use Mojo::Exception qw(check raise);
use Mojo::File 'path';
+package MojoTest::X::Foo;
+use Mojo::Base 'Mojo::Exception';
+
+package MojoTest::X::Bar;
+use Mojo::Base 'Mojo::Exception';
+
+package MojoTest::X::Yada;
+use Mojo::Base 'MojoTest::X::Bar';
+
+package main;
+
+# Verbose
+{
+ ok(!Mojo::Exception->new->verbose, 'not verbose');
+ local $ENV{MOJO_EXCEPTION_VERBOSE} = 1;
+ ok(Mojo::Exception->new->verbose, 'verbose');
+}
+
# Basics
my $e = Mojo::Exception->new;
is $e->message, 'Exception!', 'right message';
-is "$e", 'Exception!', 'right message';
+is "$e", "Exception!\n", 'right message';
$e = Mojo::Exception->new('Test!');
is $e->message, 'Test!', 'right message';
-is "$e", 'Test!', 'right message';
+is "$e", "Test!\n", 'right message';
# Context information
my $line = __LINE__;
@@ -26,31 +44,31 @@
};
$e = $@;
isa_ok $e, 'Mojo::Exception', 'right class';
-is $e, 'Works!', 'right result';
+like $e->inspect, qr/^Works!/, 'right result';
like $e->frames->[0][1], qr/exception\.t/, 'right file';
-is $e->lines_before->[0][0], $line + 1, 'right number';
-is $e->lines_before->[0][1], 'eval {', 'right line';
-is $e->lines_before->[1][0], $line + 2, 'right number';
-ok !$e->lines_before->[1][1], 'empty line';
-is $e->lines_before->[2][0], $line + 3, 'right number';
-is $e->lines_before->[2][1], ' # test', 'right line';
-is $e->lines_before->[3][0], $line + 4, 'right number';
-ok !$e->lines_before->[3][1], 'empty line';
-is $e->lines_before->[4][0], $line + 5, 'right number';
-is $e->lines_before->[4][1],
- " my \$wrapper = sub { Mojo::Exception->throw('Works!') };", 'right line';
-is $e->line->[0], $line + 6, 'right number';
-is $e->line->[1], " \$wrapper->();", 'right line';
-is $e->lines_after->[0][0], $line + 7, 'right number';
-ok !$e->lines_after->[0][1], 'empty line';
-is $e->lines_after->[1][0], $line + 8, 'right number';
-is $e->lines_after->[1][1], ' # test', 'right line';
-is $e->lines_after->[2][0], $line + 9, 'right number';
-ok !$e->lines_after->[2][1], 'empty line';
-is $e->lines_after->[3][0], $line + 10, 'right number';
-is $e->lines_after->[3][1], '};', 'right line';
-is $e->lines_after->[4][0], $line + 11, 'right number';
-is $e->lines_after->[4][1], '$e = $@;', 'right line';
+is $e->lines_before->[0][0], $line, 'right number';
+is $e->lines_before->[0][1], 'my $line = __LINE__;', 'right line';
+is $e->lines_before->[1][0], $line + 1, 'right number';
+is $e->lines_before->[1][1], 'eval {', 'right line';
+is $e->lines_before->[2][0], $line + 2, 'right number';
+ok !$e->lines_before->[2][1], 'empty line';
+is $e->lines_before->[3][0], $line + 3, 'right number';
+is $e->lines_before->[3][1], ' # test', 'right line';
+is $e->lines_before->[4][0], $line + 4, 'right number';
+ok !$e->lines_before->[4][1], 'empty line';
+is $e->line->[0], $line + 5, 'right number';
+is $e->line->[1], " my \$wrapper = sub { Mojo::Exception->throw('Works!') };",
+ 'right line';
+is $e->lines_after->[0][0], $line + 6, 'right number';
+is $e->lines_after->[0][1], ' $wrapper->();', 'right line';
+is $e->lines_after->[1][0], $line + 7, 'right number';
+ok !$e->lines_after->[1][1], 'empty line';
+is $e->lines_after->[2][0], $line + 8, 'right number';
+is $e->lines_after->[2][1], ' # test', 'right line';
+is $e->lines_after->[3][0], $line + 9, 'right number';
+ok !$e->lines_after->[3][1], 'empty line';
+is $e->lines_after->[4][0], $line + 10, 'right number';
+is $e->lines_after->[4][1], '};', 'right line';
# Trace
sub wrapper2 { Mojo::Exception->new->trace(@_) }
@@ -70,7 +88,7 @@
is_deeply $e->lines_before->[-1], [2, 'use warnings;'], 'right line';
is_deeply $e->line, [3, 'use utf8;'], 'right line';
is_deeply $e->lines_after->[0], [4, ''], 'right line';
-$e->message("Died at $file line 4.")->inspect;
+$e = Mojo::Exception->new("Died at $file line 4.")->inspect;
is_deeply $e->lines_before->[-1], [3, 'use utf8;'], 'right line';
is_deeply $e->line, [4, ''], 'right line';
is_deeply $e->lines_after->[0], [5, "my \$s = 'Über•résumé';"],
@@ -82,18 +100,22 @@
is_deeply $e->lines_before, [], 'no lines';
is_deeply $e->line, [], 'no line';
is_deeply $e->lines_after, [], 'no lines';
-$e->inspect;
+$e->inspect->inspect;
is_deeply $e->lines_before->[-1], [2, 'use warnings;'], 'right line';
is_deeply $e->line, [3, 'no utf8;'], 'right line';
is_deeply $e->lines_after->[0], [4, ''], 'right line';
-$e->message("Died at $file line 4.")->inspect;
+$e = Mojo::Exception->new("Died at $file line 4.")->inspect;
is_deeply $e->lines_before->[-1], [3, 'no utf8;'], 'right line';
is_deeply $e->line, [4, ''], 'right line';
is_deeply $e->lines_after->[0], [5, "my \$s = '\xDCber\x95r\xE9sum\xE9';"],
'right line';
-# Verbose
-$e = Mojo::Exception->new('Test!')->verbose(1);
+# Context
+$e = Mojo::Exception->new;
+is $e, "Exception!\n", 'right result';
+$e = Mojo::Exception->new->inspect->inspect;
+is $e, "Exception!\n", 'right result';
+$e = Mojo::Exception->new('Test!');
$e->frames([
['Sandbox', 'template', 4],
['MyApp::Test', 'MyApp/Test.pm', 3],
@@ -103,20 +125,199 @@
->lines_after([[5, 'bar();']]);
is $e, <<EOF, 'right result';
Test!
-3: foo();
-4: die;
-5: bar();
-template:4 (Sandbox)
-MyApp/Test.pm:3 (MyApp::Test)
-foo.pl:4 (main)
+Context:
+ 3: foo();
+ 4: die;
+ 5: bar();
+Traceback (most recent call first):
+ File "template", line 4, in "Sandbox"
+ File "MyApp/Test.pm", line 3, in "MyApp::Test"
+ File "foo.pl", line 4, in "main"
EOF
$e->message("Works!\n")->lines_before([])->lines_after([]);
is $e, <<EOF, 'right result';
Works!
-4: die;
-template:4 (Sandbox)
-MyApp/Test.pm:3 (MyApp::Test)
-foo.pl:4 (main)
+Context:
+ 4: die;
+Traceback (most recent call first):
+ File "template", line 4, in "Sandbox"
+ File "MyApp/Test.pm", line 3, in "MyApp::Test"
+ File "foo.pl", line 4, in "main"
+EOF
+
+# Verbose
+$e = Mojo::Exception->new('Test!');
+$e->frames([
+ ['Sandbox', 'template', 4],
+ ['MyApp::Test', 'MyApp/Test.pm', 3],
+ ['MyApp::Test', 'MyApp/Test.pm', 4],
+ ['MyApp::Test', 'MyApp/Test.pm', 5],
+ ['MyApp::Test', 'MyApp/Test.pm', 6],
+ ['main', 'foo.pl', 4]
+]);
+is $e, <<EOF, 'right result';
+Test!
+Traceback (most recent call first):
+ File "template", line 4, in "Sandbox"
+ File "MyApp/Test.pm", line 3, in "MyApp::Test"
+ File "MyApp/Test.pm", line 4, in "MyApp::Test"
+ File "MyApp/Test.pm", line 5, in "MyApp::Test"
+ File "MyApp/Test.pm", line 6, in "MyApp::Test"
+ ...
+EOF
+is $e->verbose(1), <<EOF, 'right result';
+Test!
+Traceback (most recent call first):
+ File "template", line 4, in "Sandbox"
+ File "MyApp/Test.pm", line 3, in "MyApp::Test"
+ File "MyApp/Test.pm", line 4, in "MyApp::Test"
+ File "MyApp/Test.pm", line 5, in "MyApp::Test"
+ File "MyApp/Test.pm", line 6, in "MyApp::Test"
+ File "foo.pl", line 4, in "main"
EOF
+# Missing error
+$e = Mojo::Exception->new->inspect;
+is_deeply $e->lines_before, [], 'no lines';
+is_deeply $e->line, [], 'no line';
+is_deeply $e->lines_after, [], 'no lines';
+is $e->message, 'Exception!', 'right message';
+$e = Mojo::Exception->new(undef)->inspect;
+is_deeply $e->lines_before, [], 'no lines';
+is_deeply $e->line, [], 'no line';
+is_deeply $e->lines_after, [], 'no lines';
+is $e->message, 'Exception!', 'right message';
+$e = Mojo::Exception->new('')->inspect;
+is_deeply $e->lines_before, [], 'no lines';
+is_deeply $e->line, [], 'no line';
+is_deeply $e->lines_after, [], 'no lines';
+is $e->message, '', 'right message';
+
+# Check (string exception)
+my $result;
+eval { die "test1\n" };
+ok check(default => sub { $result = $_ }), 'exception handled';
+is $result, "test1\n", 'exception arrived in handler';
+$result = undef;
+eval { die "test2\n" };
+ok check(default => sub { $result = shift }), 'exception handled';
+is $result, "test2\n", 'exception arrived in handler';
+$result = undef;
+eval { die "test3\n" };
+check
+ default => sub { $result = 'fail' },
+ qr/^test2/ => sub { $result = 'fail' },
+ qr/^test3/ => sub { $result = 'test10' },
+ qr/^test4/ => sub { $result = 'fail' };
+is $result, 'test10', 'regular expression matched';
+$result = undef;
+check "test4\n",
+ qr/^test3/ => sub { $result = 'fail' },
+ qr/^test4/ => sub { $result = 'test11' },
+ qr/^test5/ => sub { $result = 'fail' };
+is $result, 'test11', 'regular expression matched';
+
+# Check (exception objects)
+$result = undef;
+eval { MojoTest::X::Foo->throw('fail') };
+check
+ default => sub { $result = 'fail' },
+ 'MojoTest::X::Foo' => sub { $result = 'test12' },
+ 'MojoTest::X::Bar' => sub { $result = 'fail' };
+is $result, 'test12', 'class matched';
+$result = undef;
+eval { MojoTest::X::Bar->throw('fail') };
+check
+ 'MojoTest::X::Foo' => sub { $result = 'fail' },
+ 'MojoTest::X::Bar' => sub { $result = 'test13' };
+is $result, 'test13', 'class matched';
+$result = undef;
+check(
+ MojoTest::X::Yada->new('fail'),
+ qr/^MojoTest/ => sub { $result = 'fail' },
+ 'MojoTest::X::Foo' => sub { $result = 'fail' },
+ 'MojoTest::X::Bar' => sub { $result = 'test14' }
+);
+is $result, 'test14', 'class matched';
+$result = undef;
+check(
+ MojoTest::X::Yada->new('whatever'),
+ 'MojoTest::X::Foo' => sub { $result = 'fail' },
+ qr/^whatever/ => sub { $result = 'test23' },
+);
+is $result, 'test23', 'regex matched';
+
+# Check (multiple)
+$result = undef;
+check(
+ MojoTest::X::Yada->new('whatever'),
+ ['MojoTest::X::Foo', 'MojoTest::X::Bar'] => sub { $result = 'test15' },
+ default => sub { $result = 'fail' }
+);
+is $result, 'test15', 'class matched';
+$result = undef;
+check(
+ MojoTest::X::Bar->new('whatever'),
+ ['MojoTest::X::Foo', 'MojoTest::X::Yada'] => sub { $result = 'fail' },
+ ['MojoTest::X::Bar'] => sub { $result = 'test16' }
+);
+is $result, 'test16', 'class matched';
+
+# Check (rethrow)
+eval {
+ check "test5\n", qr/test4/ => sub { die 'fail' };
+};
+is $@, "test5\n", 'exception has been rethrown';
+
+# Check (finally)
+my $finally;
+eval {
+ check "test7\n", finally => sub { $finally = 'finally7' };
+};
+is $@, "test7\n", 'exception has been rethrown';
+is $finally, 'finally7', 'finally handler used';
+$result = [];
+check "test8\n",
+ qr/test7/ => sub { push @$result, 'fail' },
+ default => sub { push @$result, $_ },
+ finally => sub { push @$result, 'finally8' };
+is_deeply $result, ["test8\n", 'finally8'], 'default and finally handlers
used';
+$finally = undef;
+eval {
+ check "fail\n",
+ default => sub { die "test17\n" },
+ finally => sub { $finally = 'finally17' };
+};
+is $@, "test17\n", 'right exception';
+is $finally, 'finally17', 'finally handler used';
+
+# Check (nothing)
+ok !check(undef, default => sub { die 'fail' }), 'no exception';
+{
+ local $@;
+ ok !check(default => sub { die 'fail' }), 'no exception';
+}
+
+# Raise
+eval { raise 'MyApp::X::Baz', 'test19' };
+my $err = $@;
+isa_ok $err, 'MyApp::X::Baz', 'is a MyApp::X::Baz';
+isa_ok $err, 'Mojo::Exception', 'is a Mojo::Exception';
+like $err, qr/^test19/, 'right error';
+eval { raise 'MyApp::X::Baz', 'test20' };
+$err = $@;
+isa_ok $err, 'MyApp::X::Baz', 'is a MyApp::X::Baz';
+isa_ok $err, 'Mojo::Exception', 'is a Mojo::Exception';
+like $err, qr/^test20/, 'right error again';
+eval { raise 'test22' };
+$err = $@;
+isa_ok $err, 'Mojo::Exception', 'is a Mojo::Exception';
+like $err, qr/^test22/, 'right error';
+eval { raise 'MojoTest::X::Foo', 'test21' };
+$err = $@;
+isa_ok $err, 'MojoTest::X::Foo', 'is a MojoTest::X::Baz';
+like $err, qr/^test21/, 'right error';
+eval { raise 'Mojo::Base', 'fail' };
+like $@, qr/^Mojo::Base is not a Mojo::Exception subclass/, 'right error';
+
done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/t/mojo/template.t
new/Mojolicious-8.21/t/mojo/template.t
--- old/Mojolicious-8.18/t/mojo/template.t 2019-05-31 21:29:02.000000000
+0200
+++ new/Mojolicious-8.21/t/mojo/template.t 2019-07-07 23:47:35.000000000
+0200
@@ -607,7 +607,6 @@
EOF
isa_ok $output, 'Mojo::Exception', 'right exception';
is $output->message, "x\n", 'right message';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][0], 1, 'right number';
is $output->lines_before->[0][1], 'test', 'right line';
is $output->lines_before->[1][0], 2, 'right number';
@@ -629,7 +628,6 @@
EOF
isa_ok $output, 'Mojo::Exception', 'right exception';
like $output->message, qr/Missing right curly/, 'right message';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][0], 1, 'right number';
is $output->lines_before->[0][1], 'test', 'right line';
is $output->lines_before->[1][0], 2, 'right number';
@@ -654,7 +652,6 @@
EOF
isa_ok $output, 'Mojo::Exception', 'right exception';
like $output->message, qr/ohoh/, 'right message';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][0], 14, 'right number';
is $output->lines_before->[0][1], '}', 'right line';
is $output->lines_before->[1][0], 15, 'right number';
@@ -686,7 +683,6 @@
EOF
isa_ok $output, 'Mojo::Exception', 'right exception';
like $output->message, qr/oops!/, 'right message';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][0], 1, 'right number';
is $output->lines_before->[0][1], 'test', 'right line';
is $output->lines_before->[1][0], 2, 'right number';
@@ -704,15 +700,17 @@
$output->frames([['Sandbox', 'template', 5], ['main', 'template.t', 673]]);
is $output, <<EOF, 'right result';
oops! at template line 5.
-1: test
-2: 123\\
-3: 456
-4: %# This dies
-5: % die 'oops!';
-6: %= 1 + 1
-7: test
-template:5 (Sandbox)
-template.t:673 (main)
+Context:
+ 1: test
+ 2: 123\\
+ 3: 456
+ 4: %# This dies
+ 5: % die 'oops!';
+ 6: %= 1 + 1
+ 7: test
+Traceback (most recent call first):
+ File "template", line 5, in "Sandbox"
+ File "template.t", line 673, in "main"
EOF
# Exception in template (empty perl lines)
@@ -730,7 +728,6 @@
EOF
isa_ok $output, 'Mojo::Exception', 'right exception';
like $output->message, qr/oops!/, 'right message';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][0], 1, 'right number';
is $output->lines_before->[0][1], 'test\\\\', 'right line';
ok $output->lines_before->[0][2], 'contains code';
@@ -767,8 +764,7 @@
-$]
$-= $output
EOF
-like $output,
- qr/test\n\nBareword "bar".+in use at template line 1\.\n1: %= bar/,
+like $output, qr/test\n\nBareword "bar".+in use at template line 1\./,
'exception in nested template';
# Control structures
@@ -1139,7 +1135,6 @@
$output = $mt->render_file($file);
isa_ok $output, 'Mojo::Exception', 'right exception';
like $output->message, qr/exception\.mt line 2/, 'message contains filename';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][0], 1, 'right number';
is $output->lines_before->[0][1], 'test', 'right line';
is $output->line->[0], 2, 'right number';
@@ -1154,7 +1149,6 @@
isa_ok $output, 'Mojo::Exception', 'right exception';
like $output->message, qr/foo\.mt from DATA section line 2/,
'message contains filename';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][0], 1, 'right number';
is $output->lines_before->[0][1], 'test', 'right line';
is $output->line->[0], 2, 'right number';
@@ -1168,7 +1162,6 @@
$file = path(__FILE__)->sibling('templates', 'utf8_exception.mt');
$output = $mt->render_file($file);
isa_ok $output, 'Mojo::Exception', 'right exception';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0][1], '☃', 'right line';
is $output->line->[1], '% die;♥', 'right line';
is $output->lines_after->[0][1], '☃', 'right line';
@@ -1178,7 +1171,6 @@
$output = $mt->render('<% die "Test at template line 99\n"; %>');
isa_ok $output, 'Mojo::Exception', 'right exception';
is $output->message, "Test at template line 99\n", 'right message';
-ok $output->verbose, 'verbose exception';
is $output->lines_before->[0], undef, 'no lines before';
is $output->line->[0], 1, 'right number';
is $output->line->[1], '<% die "Test at template line 99\n"; %>', 'right line';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/t/mojolicious/commands.t
new/Mojolicious-8.21/t/mojolicious/commands.t
--- old/Mojolicious-8.18/t/mojolicious/commands.t 2019-05-31
21:29:08.000000000 +0200
+++ new/Mojolicious-8.21/t/mojolicious/commands.t 2019-07-03
16:54:52.000000000 +0200
@@ -330,6 +330,16 @@
ok -e $app->rel_file('Mojolicious-Plugin-MyPlugin/t/basic.t'), 'test exists';
ok -e $app->rel_file('Mojolicious-Plugin-MyPlugin/Makefile.PL'),
'Makefile.PL exists';
+$buffer = '';
+{
+ open my $handle, '>', \$buffer;
+ local *STDOUT = $handle;
+ $plugin->run('-f', 'MyApp::Ext::Test');
+}
+like $buffer, qr/Test\.pm/, 'right output';
+ok -e $app->rel_file('MyApp-Ext-Test/lib/MyApp/Ext/Test.pm'), 'class exists';
+ok -e $app->rel_file('MyApp-Ext-Test/t/basic.t'), 'test exists';
+ok -e $app->rel_file('MyApp-Ext-Test/Makefile.PL'), 'Makefile.PL exists';
chdir $cwd;
# inflate
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/t/mojolicious/exception_lite_app.t
new/Mojolicious-8.21/t/mojolicious/exception_lite_app.t
--- old/Mojolicious-8.18/t/mojolicious/exception_lite_app.t 2019-05-31
21:29:07.000000000 +0200
+++ new/Mojolicious-8.21/t/mojolicious/exception_lite_app.t 2019-07-13
21:36:18.000000000 +0200
@@ -113,7 +113,7 @@
hook around_dispatch => sub {
my ($next, $c) = @_;
unless (eval { $next->(); 1 }) {
- die $@ unless $@ eq "CUSTOM\n";
+ die $@ unless $@ =~ /^CUSTOM\n/;
$c->render(text => 'Custom handling works!');
}
};
@@ -126,6 +126,17 @@
my $t = Test::Mojo->new;
+# Missing error
+my $c = $t->app->build_controller;
+$c->reply->exception(undef);
+like $c->res->body, qr/Exception!/, 'right result';
+$c = $t->app->build_controller;
+$c->reply->exception;
+like $c->res->body, qr/Exception!/, 'right result';
+$c = $t->app->build_controller;
+$c->reply->exception(Mojo::Exception->new);
+like $c->res->body, qr/Exception!/, 'right result';
+
# Debug
$t->get_ok('/logger?level=debug&message=one')->status_is(200)
->content_is('debug: one');
@@ -211,11 +222,13 @@
# Dead action with custom exception rendering
$t->get_ok('/dead_action' => {Accept => 'text/plain'})->status_is(500)
- ->content_type_is('text/plain;charset=UTF-8')->content_is("dead action!\n");
+ ->content_type_is('text/plain;charset=UTF-8')
+ ->content_like(qr/^dead action!\n/);
# Action dies twice
$t->get_ok('/double_dead_action_☃')->status_is(500)
- ->content_like(qr!get '/double_dead_action_☃'.*lite_app\.t:\d!s)
+ ->content_like(qr!get '/double_dead_action_☃'!)
+ ->content_like(qr/File.+lite_app\.t\", line \d/)
->content_like(qr/double dead action!/);
# Trapped exception
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/t/mojolicious/validation_lite_app.t
new/Mojolicious-8.21/t/mojolicious/validation_lite_app.t
--- old/Mojolicious-8.18/t/mojolicious/validation_lite_app.t 2019-05-31
21:29:03.000000000 +0200
+++ new/Mojolicious-8.21/t/mojolicious/validation_lite_app.t 2019-07-09
19:25:28.000000000 +0200
@@ -158,6 +158,11 @@
ok !$v->required('foo')->num(undef, 22)->is_valid, 'not valid';
ok $v->has_error, 'has error';
is_deeply $v->error('foo'), ['num', 1, undef, 22], 'right error';
+$v = $t->app->validation->input({foo => -5});
+ok $v->required('foo')->num->is_valid, 'valid';
+ok $v->required('foo')->num(undef, -1)->is_valid, 'valid';
+ok $v->required('foo')->num(-10, 10)->is_valid, 'valid';
+ok $v->required('foo')->num(-20, undef)->is_valid, 'valid';
# Size
$v = $t->app->validation->input({foo => 'bar', baz => 'yada', yada => 'yada'});
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/Mojolicious-8.18/t/pod_coverage.t
new/Mojolicious-8.21/t/pod_coverage.t
--- old/Mojolicious-8.18/t/pod_coverage.t 2019-06-21 23:12:48.000000000
+0200
+++ new/Mojolicious-8.21/t/pod_coverage.t 2019-07-07 23:48:36.000000000
+0200
@@ -7,4 +7,5 @@
plan skip_all => 'Test::Pod::Coverage 1.04+ required for this test!'
unless eval 'use Test::Pod::Coverage 1.04; 1';
-all_pod_coverage_ok({also_private => ['BUILD_DYNAMIC', 'slice', 'success']});
+all_pod_coverage_ok(
+ {also_private => ['BUILD_DYNAMIC', 'slice', 'success', 'verbose']});