File Coverage

blib/lib/Class/More.pm
Criterion Covered Total %
statement 168 176 95.4
branch 47 62 75.8
condition 13 31 41.9
subroutine 25 28 89.2
pod 2 3 66.6
total 255 300 85.0


line stmt bran cond sub pod time code
1             package Class::More;
2              
3 22     22   854184 use strict;
  22         39  
  22         766  
4 22     22   93 use warnings;
  22         42  
  22         1048  
5 22     22   3677 use version;
  22         16869  
  22         129  
6              
7             our $VERSION = qv('v0.1.1');
8             our $AUTHORITY = 'cpan:MANWAR';
9              
10             my %ACCESSOR_CACHE;
11             my %BUILD_ORDER_CACHE;
12             my %PARENT_LOADED_CACHE;
13             my %ALL_ATTRIBUTES_CACHE;
14             our %ATTRIBUTES;
15              
16             sub _generate_fast_accessor {
17 80     80   124 my ($attr_name) = @_;
18              
19             return $ACCESSOR_CACHE{$attr_name} ||= sub {
20 90 100   90   3223 $_[0]{$attr_name} = $_[1] if @_ > 1;
21 90         323 return $_[0]{$attr_name};
22 80   66     702 };
23             }
24              
25             sub import {
26 59     59   423 my ($class, @args) = @_;
27 59         112 my $caller = caller;
28              
29 59         586 strict->import;
30 59         1031 warnings->import;
31              
32 22     22   5067 no strict 'refs';
  22         50  
  22         14620  
33              
34             # Install optimised new method
35 59         121 *{"${caller}::new"} = _generate_optimised_constructor($caller);
  59         263  
36              
37             # Install has method
38 59         90 *{"${caller}::has"} = \&_has;
  59         154  
39              
40             # Install extends method
41 59         93 *{"${caller}::extends"} = \&_extends;
  59         195  
42              
43             # Load Role.pm if available
44 59         97 eval { require Role };
  59         4932  
45 59 50       160 if (!$@) {
46 59         74 *{"${caller}::with"} = \&Role::with;
  59         218  
47 59         70 *{"${caller}::does"} = \&Role::does;
  59         172  
48             }
49              
50 59 50 33     31535 if (@args && $args[0] eq 'extends') {
51 0         0 _extends($caller, @args[1..$#args]);
52             }
53             }
54              
55             sub _generate_optimised_constructor {
56 59     59   83 my $class = shift;
57              
58             return sub {
59 58     58   8338 my $class = shift;
60 58         110 my %args = @_;
61              
62             # Fast path: bless hashref directly for maximum speed
63 58         99 my $self = bless {}, $class;
64              
65             # Get cached attributes
66 58         110 my $class_attrs = _get_all_attributes_fast($class);
67              
68             # Ultra-fast path: no attributes, no BUILD methods
69 58 100       120 unless (%$class_attrs) {
70 3   33     11 my $build_methods = $BUILD_ORDER_CACHE{$class} ||= _compute_build_methods_fast($class);
71 3 100       7 unless (@$build_methods) {
72             # Absolute fastest path: just copy args and return
73 2         7 %$self = %args;
74 2         6 return $self;
75             }
76             }
77              
78             # Make args copy for defaults
79 56         102 my %args_copy = %args;
80              
81             # Process attributes efficiently
82 56         134 _process_attributes_ultra_fast($class, $self, \%args, \%args_copy, $class_attrs);
83              
84             # Copy remaining args
85 47         151 while (my ($key, $value) = each %args) {
86 3 50       17 $self->{$key} = $value unless exists $self->{$key};
87             }
88              
89             # Call BUILD methods if any
90 47   66     184 my $build_methods = $BUILD_ORDER_CACHE{$class} ||= _compute_build_methods_fast($class);
91 47 100       75 if (@$build_methods) {
92 3         14 $_->($self, \%args_copy) for @$build_methods;
93             }
94              
95 47         156 return $self;
96 59         436 };
97             }
98              
99             sub _process_attributes_ultra_fast {
100 56     56   108 my ($class, $self, $args, $args_copy, $class_attrs) = @_;
101              
102 56         63 my @required_check;
103              
104             # PASS 1: Constructor values with minimal operations
105 56         102 foreach my $attr_name (keys %$class_attrs) {
106 133         144 my $spec = $class_attrs->{$attr_name};
107              
108 133 100       180 if (exists $args->{$attr_name}) {
109 35         95 $self->{$attr_name} = $args->{$attr_name};
110 35         42 delete $args->{$attr_name};
111 35         50 next;
112             }
113              
114 98 100       245 push @required_check, $attr_name if $spec->{required};
115             }
116              
117             # PASS 2: Defaults
118 56         90 foreach my $attr_name (keys %$class_attrs) {
119 133 100       324 next if exists $self->{$attr_name};
120              
121 98         101 my $spec = $class_attrs->{$attr_name};
122 98 100       148 if (exists $spec->{default}) {
123 78         85 my $default = $spec->{default};
124 78 100       214 $self->{$attr_name} = ref $default eq 'CODE'
125             ? $default->($self, $args_copy)
126             : $default;
127             }
128             }
129              
130             # PASS 3: Required attributes (only if any exist)
131 56 100       134 if (@required_check) {
132 10         16 foreach my $attr_name (@required_check) {
133 11 100       31 unless (defined $self->{$attr_name}) {
134 9         124 die "Required attribute '$attr_name' not provided for class $class";
135             }
136             }
137             }
138             }
139              
140             sub _get_all_attributes_fast {
141 60     60   96 my ($class) = @_;
142              
143 60 100       142 return $ALL_ATTRIBUTES_CACHE{$class} if exists $ALL_ATTRIBUTES_CACHE{$class};
144              
145 40         56 my %all_attrs;
146              
147             # Current class
148 40 100       93 if (my $current_attrs = $ATTRIBUTES{$class}) {
149 35         102 %all_attrs = %$current_attrs;
150             }
151              
152             # Parents
153 22     22   164 no strict 'refs';
  22         30  
  22         3660  
154 40         49 my @isa = @{"${class}::ISA"};
  40         169  
155 40         51 foreach my $parent (@isa) {
156 23 50 33     145 next if $parent eq 'Class::More' || $parent eq 'UNIVERSAL';
157 23 100       102 if (my $parent_attrs = $ATTRIBUTES{$parent}) {
158 10         48 %all_attrs = (%$parent_attrs, %all_attrs);
159             }
160             }
161              
162 40         98 return $ALL_ATTRIBUTES_CACHE{$class} = \%all_attrs;
163             }
164              
165             sub _compute_build_methods_fast {
166 40     40   100 my ($class) = @_;
167              
168 40         81 my @inheritance_tree = _get_inheritance_tree_dfs($class);
169 40         41 my @build_methods;
170              
171 40         48 foreach my $c (@inheritance_tree) {
172 22     22   112 no strict 'refs';
  22         35  
  22         2903  
173 65 100       57 if (defined &{"${c}::BUILD"}) {
  65         228  
174 6         5 push @build_methods, \&{"${c}::BUILD"};
  6         12  
175             }
176             }
177              
178 40         98 return \@build_methods;
179             }
180              
181             # Efficient DFS
182             sub _get_inheritance_tree_dfs {
183 65     65   86 my ($class, $visited) = @_;
184 65   100     192 $visited ||= {};
185              
186 65 50 33     201 return () if $visited->{$class} || !defined $class;
187 65         99 $visited->{$class} = 1;
188              
189 65         104 my @order;
190              
191 22     22   105 no strict 'refs';
  22         35  
  22         3728  
192 65         85 my @isa = @{"${class}::ISA"};
  65         173  
193              
194 65         84 foreach my $parent (@isa) {
195 25 50 33     191 next if !defined $parent || $parent eq 'Class::More' || $parent eq 'UNIVERSAL' || $parent eq '';
      33        
      33        
196 25         79 push @order, _get_inheritance_tree_dfs($parent, $visited);
197             }
198              
199 65         89 push @order, $class;
200 65         187 return @order;
201             }
202              
203             sub _has {
204 80     80   1452137 my ($attr_name, %spec) = @_;
205 80         163 my $current_class = caller;
206              
207 80         689 _clear_attributes_cache($current_class);
208              
209 80 100       204 $ATTRIBUTES{$current_class} = {} unless exists $ATTRIBUTES{$current_class};
210 80         213 $ATTRIBUTES{$current_class}{$attr_name} = \%spec;
211              
212 22     22   145 no strict 'refs';
  22         48  
  22         4659  
213 80 50       87 if (!defined &{"${current_class}::${attr_name}"}) {
  80         414  
214 80         159 *{"${current_class}::${attr_name}"} = _generate_fast_accessor($attr_name);
  80         307  
215             }
216             }
217              
218             sub _extends {
219 10     10   945 my $caller = caller;
220 10         62 my @parents = @_;
221              
222 10         23 _delete_build_cache($caller);
223 10         24 _clear_attributes_cache($caller);
224              
225 10         18 for my $parent_class (@parents) {
226 12 50       27 die "Recursive inheritance detected: $caller cannot extend itself"
227             if $caller eq $parent_class;
228              
229 12 50       29 unless ($PARENT_LOADED_CACHE{$parent_class}) {
230 12         18 my $parent_file = "$parent_class.pm";
231 12         41 $parent_file =~ s{::}{/}g;
232              
233 12 50       33 unless ($INC{$parent_file}) {
234 12         14 eval { require $parent_file };
  12         4979  
235             }
236 12         42 $PARENT_LOADED_CACHE{$parent_class} = 1;
237             }
238              
239 22     22   111 no strict 'refs';
  22         37  
  22         5235  
240 12 50       14 unless (grep { $_ eq $parent_class } @{"${caller}::ISA"}) {
  2         6  
  12         83  
241 12         15 push @{"${caller}::ISA"}, $parent_class;
  12         120  
242             }
243             }
244             }
245              
246             sub _delete_build_cache {
247 10     10   16 my ($class) = @_;
248 10         14 delete $BUILD_ORDER_CACHE{$class};
249 10         23 for my $cached_class (keys %BUILD_ORDER_CACHE) {
250 30 50       35 if (_inherits_from_fast($cached_class, $class)) {
251 0         0 delete $BUILD_ORDER_CACHE{$cached_class};
252             }
253             }
254             }
255              
256             sub _inherits_from_fast {
257 399     399   351 my ($class, $parent) = @_;
258 22     22   130 no strict 'refs';
  22         34  
  22         7528  
259 399         278 my @isa = @{"${class}::ISA"};
  399         684  
260 399 50       413 return 1 if grep { $_ eq $parent } @isa;
  99         174  
261 399         318 foreach my $direct_parent (@isa) {
262 99 50       104 return 1 if _inherits_from_fast($direct_parent, $parent);
263             }
264 399         590 return 0;
265             }
266              
267             sub _clear_attributes_cache {
268 90     90   109 my ($class) = @_;
269 90         101 delete $ALL_ATTRIBUTES_CACHE{$class};
270 90         191 for my $cached_class (keys %ALL_ATTRIBUTES_CACHE) {
271 270 50       270 if (_inherits_from_fast($cached_class, $class)) {
272 0         0 delete $ALL_ATTRIBUTES_CACHE{$cached_class};
273             }
274             }
275             }
276              
277 0     0 1 0 sub can_handle_attributes { 1 }
278              
279             sub meta {
280 0     0 1 0 my $class = shift;
281             return {
282             can_handle_attributes => 1,
283 0   0     0 attributes => $ATTRIBUTES{$class} || {},
284             };
285             }
286              
287             sub get_all_attributes {
288 0     0 0 0 my ($class) = @_;
289 0         0 return _get_all_attributes_fast($class);
290             }
291              
292             sub _get_all_attributes {
293 2     2   56 my ($class) = @_;
294 2         4 return _get_all_attributes_fast($class);
295             }
296              
297             =head1 NAME
298              
299             Class::More - A fast, lightweight class builder for Perl
300              
301             =head1 VERSION
302              
303             Version v0.1.1
304              
305             =head1 SYNOPSIS
306              
307             package My::Class;
308             use Class::More;
309              
310             # Define attributes
311             has 'name' => ( required => 1 );
312             has 'age' => ( default => 0 );
313             has 'tags' => ( default => sub { [] } );
314              
315             # Set up inheritance
316             extends 'My::Parent';
317              
318             # Custom constructor logic
319             sub BUILD {
320             my ($self, $args) = @_;
321             $self->{initialized} = time;
322             }
323              
324             sub greet {
325             my $self = shift;
326             return "Hello, " . $self->name;
327             }
328              
329             1;
330              
331             # Usage
332             my $obj = My::Class->new(
333             name => 'Alice',
334             age => 30
335             );
336              
337             print $obj->name; # Alice
338             print $obj->age; # 30
339              
340             =head1 DESCRIPTION
341              
342             Class::More provides a fast, lightweight class building system for Perl with
343             attribute support, inheritance, and constructor building. It's designed for
344             performance and simplicity while providing essential object-oriented features.
345              
346             The module focuses on speed with optimized method generation, caching, and
347             minimal runtime overhead.
348              
349             =head1 FEATURES
350              
351             =head2 Core Features
352              
353             =over 4
354              
355             =item * B: Simple attributes with required flags and defaults
356              
357             =item * B: Automatically generates getter/setter methods
358              
359             =item * B: Multiple inheritance with proper method resolution
360              
361             =item * B: Constructor-time initialisation hooks
362              
363             =item * B: Extensive caching and optimised code paths
364              
365             =item * B: Works seamlessly with L when available
366              
367             =back
368              
369             =head2 Performance Features
370              
371             =over 4
372              
373             =item * Pre-generated accessors for maximum speed
374              
375             =item * Method resolution order caching
376              
377             =item * Attribute specification caching
378              
379             =item * Fast inheritance checks
380              
381             =item * Batch accessor installation
382              
383             =back
384              
385             =head1 METHODS
386              
387             =head2 Class Definition Methods
388              
389             These methods are exported to your class when you C.
390              
391             =head3 has
392              
393             has 'attribute_name';
394             has 'count' => ( default => 0 );
395             has 'items' => ( default => sub { [] } );
396             has 'name' => ( required => 1 );
397              
398             Defines an attribute in your class. Creates an accessor method that can get
399             and set the attribute value.
400              
401             Supported options:
402              
403             =over 4
404              
405             =item * C - Default value or code reference that returns default value
406              
407             =item * C - Boolean indicating if attribute must be provided to constructor
408              
409             =back
410              
411             =head3 extends
412              
413             extends 'Parent::Class';
414             extends 'Parent1', 'Parent2';
415              
416             Sets up inheritance for your class. Can specify multiple parents for multiple
417             inheritance. Automatically loads parent classes if needed.
418              
419             =head3 new
420              
421             my $obj = My::Class->new(%attributes);
422             my $obj = My::Class->new( name => 'test', count => 42 );
423              
424             The constructor method. Automatically provided by Class::More. Handles:
425              
426             =over 4
427              
428             =item * Attribute initialisation with defaults
429              
430             =item * Required attribute validation
431              
432             =item * BUILD method calling in proper inheritance order
433              
434             =back
435              
436             =head2 Special Methods
437              
438             =head3 BUILD
439              
440             sub BUILD {
441             my ($self, $args) = @_;
442             # Custom initialization logic
443             $self->{internal_field} = process($args->{external_field});
444             }
445              
446             Optional method called after object construction but before returning from C.
447             Receives the object and the hashref of constructor arguments.
448              
449             BUILD methods are called in inheritance order (parent classes first).
450              
451             =head3 meta
452              
453             my $meta = My::Class->meta;
454             print $meta->{can_handle_attributes}; # 1
455             print keys %{$meta->{attributes}}; # name, age, tags
456              
457             Returns metadata about the class. Currently provides:
458              
459             =over 4
460              
461             =item * C - Always true
462              
463             =item * C - Hashref of attribute specifications
464              
465             =back
466              
467             =head1 ATTRIBUTE SYSTEM
468              
469             =head2 Basic Usage
470              
471             package User;
472             use Class::More;
473              
474             has 'username' => ( required => 1 );
475             has 'email' => ( required => 1 );
476             has 'status' => ( default => 'active' );
477             has 'created' => ( default => sub { time } );
478              
479             Attributes defined with C automatically get accessor methods:
480              
481             my $user = User->new(
482             username => 'alice',
483             email => 'alice@example.com'
484             );
485              
486             # Getter
487             print $user->username; # alice
488              
489             # Setter
490             $user->status('inactive');
491              
492             =head2 Required Attributes
493              
494             has 'critical_data' => ( required => 1 );
495              
496             If a required attribute is not provided to the constructor, an exception is thrown:
497              
498             # Dies: "Required attribute 'critical_data' not provided for class User"
499             User->new( username => 'test' );
500              
501             =head2 Default Values
502              
503             has 'counter' => ( default => 0 );
504             has 'list' => ( default => sub { [] } );
505             has 'complex' => ( default => sub {
506             return { computed => time }
507             });
508              
509             Defaults can be simple values or code references. Code references are executed
510             at construction time and receive the object and constructor arguments.
511              
512             =head2 Inheritance and Attributes
513              
514             package Parent;
515             use Class::More;
516             has 'parent_attr' => ( default => 'from_parent' );
517              
518             package Child;
519             use Class::More;
520             extends 'Parent';
521             has 'child_attr' => ( default => 'from_child' );
522              
523             Child classes inherit parent attributes. If both parent and child define the
524             same attribute, the child's specification takes precedence.
525              
526             =head1 PERFORMANCE OPTIMISATIONS
527              
528             Class::More includes several performance optimisations:
529              
530             =over 4
531              
532             =item * B: Simple accessors are pre-compiled and reused
533              
534             =item * B: Combined attribute specifications are cached per class
535              
536             =item * B: BUILD method call order is computed once per class
537              
538             =item * B: Optimised inheritance tree traversal
539              
540             =item * B: Multiple accessors installed in batch when possible
541              
542             =back
543              
544             =head1 EXAMPLES
545              
546             =head2 Simple Class
547              
548             package Person;
549             use Class::More;
550              
551             has 'name' => ( required => 1 );
552             has 'age' => ( default => 0 );
553              
554             sub introduce {
555             my $self = shift;
556             return "I'm " . $self->name . ", age " . $self->age;
557             }
558              
559             1;
560              
561             =head2 Class with Inheritance
562              
563             package Animal;
564             use Class::More;
565              
566             has 'species' => ( required => 1 );
567             has 'sound' => ( required => 1 );
568              
569             sub speak {
570             my $self = shift;
571             return $self->sound;
572             }
573              
574             package Dog;
575             use Class::More;
576             extends 'Animal';
577              
578             sub BUILD {
579             my ($self, $args) = @_;
580             $self->{species} = 'Canine' unless $args->{species};
581             $self->{sound} = 'Woof!' unless $args->{sound};
582             }
583              
584             sub fetch {
585             my $self = shift;
586             return $self->name . " fetches the ball!";
587             }
588              
589             =head2 Class with Complex Attributes
590              
591             package Configuration;
592             use Class::More;
593              
594             has 'settings' => ( default => sub { {} } );
595             has 'counters' => ( default => sub { { success => 0, failure => 0 } } );
596             has 'log_file' => ( required => 1 );
597              
598             sub BUILD {
599             my ($self, $args) = @_;
600              
601             # Initialize complex data structures
602             $self->{internal_cache} = {};
603             $self->{start_time} = time;
604             }
605              
606             sub increment {
607             my ($self, $counter) = @_;
608             $self->counters->{$counter}++;
609             }
610              
611             =head1 INTEGRATION WITH Role
612              
613             When L is available, Class::More automatically exports:
614              
615             =head3 with
616              
617             package My::Class;
618             use Class::More;
619              
620             with 'Role::Printable', 'Role::Serialisable';
621              
622             Composes roles into your class. See L for complete documentation.
623              
624             =head3 does
625              
626             if ($obj->does('Role::Printable')) {
627             $obj->print;
628             }
629              
630             Checks if an object consumes a specific role.
631              
632             =head1 LIMITATIONS
633              
634             =head2 Attribute System Limitations
635              
636             =over 4
637              
638             =item * B: Attributes don't support type checking
639              
640             =item * B: All attributes are readable and writable
641              
642             =item * B: No automatic value transformation
643              
644             =item * B: No callbacks when attributes change
645              
646             =item * B: Defaults are applied immediately at construction
647              
648             =item * B: All attributes are publicly accessible via accessors
649              
650             =back
651              
652             =head2 Inheritance Limitations
653              
654             =over 4
655              
656             =item * B: No compile-time method requirement checking
657              
658             =item * B: Basic metadata only
659              
660             =item * B: No trait-based composition
661              
662             =item * B: Multiple inheritance may have ambiguous method resolution
663              
664             =back
665              
666             =head2 General Limitations
667              
668             =over 4
669              
670             =item * B: Can't make classes immutable for performance
671              
672             =item * B: No built-in serialisation/deserialisation
673              
674             =item * B: No ORM-like features
675              
676             =item * B: No custom exception classes
677              
678             =back
679              
680             =head2 Compatibility Notes
681              
682             =over 4
683              
684             =item * Designed for simplicity and speed over feature completeness
685              
686             =item * Uses standard Perl OO internals (blessed hashrefs)
687              
688             =item * Compatible with most CPAN modules that expect blessed hashrefs
689              
690             =item * Not compatible with Moose/Mouse object systems
691              
692             =item * Role integration requires separate L module
693              
694             =back
695              
696             =head1 DIAGNOSTICS
697              
698             =head2 Common Errors
699              
700             =over 4
701              
702             =item * C<"Required attribute 'attribute_name' not provided for class Class::Name">
703              
704             A required attribute was not passed to the constructor.
705              
706             =item * C<"Recursive inheritance detected: ClassA cannot extend itself">
707              
708             A class tries to inherit from itself, directly or indirectly.
709              
710             =item * C<"Invalid attribute option 'option_name' for 'attribute_name' in Class::Name">
711              
712             An unsupported attribute option was used.
713              
714             =item * C<"Can't locate Parent/Class.pm in @INC">
715              
716             A parent class specified in C couldn't be loaded.
717              
718             =back
719              
720             =head2 Performance Tips
721              
722             =over 4
723              
724             =item * Use simple defaults when possible (avoid sub refs for static values)
725              
726             =item * Define all attributes before calling C for optimal caching
727              
728             =item * Keep BUILD methods lightweight
729              
730             =item * Use the provided C method rather than overriding it
731              
732             =back
733              
734             =head1 SEE ALSO
735              
736             =over 4
737              
738             =item * L - Companion role system for Class::More
739              
740             =item * L - Lightweight Moose-like OO system
741              
742             =item * L - Minimalistic base class for Mojolicious
743              
744             =item * L - Extremely lightweight class builder
745              
746             =item * L - Simple class builder with accessors
747              
748             =item * L - Full-featured object system
749              
750             =back
751              
752             =head1 AUTHOR
753              
754             Mohammad Sajid Anwar, C<< >>
755              
756             =head1 REPOSITORY
757              
758             L
759              
760             =head1 BUGS
761              
762             Please report any bugs or feature requests through the web interface at L.
763             I will be notified and then you'll automatically be notified of progress on your bug as I make changes.
764              
765             =head1 SUPPORT
766              
767             You can find documentation for this module with the perldoc command.
768              
769             perldoc Class::More
770              
771             You can also look for information at:
772              
773             =over 4
774              
775             =item * BUG Report
776              
777             L
778              
779             =back
780              
781             =head1 LICENSE AND COPYRIGHT
782              
783             Copyright (C) 2025 Mohammad Sajid Anwar.
784              
785             This program is free software; you can redistribute it and / or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:
786              
787             L
788              
789             Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
790              
791             If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
792              
793             This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
794              
795             This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
796              
797             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
798              
799             =cut
800              
801             1; # End of Class::More