The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Attribute::GlobalEnable - Enable Attrubutes and flags globally across all code.

SYNOPSIS

  package Attribute::GlobalEnable::MyPackage;
  
  use Attibute::GlobalEnable(
    ENABLE_CHK  => \%ENV,
    ENABLE_ATTR => { Debug => 'DEBUG_PERL' }
  );
  
  ## see Attribute::Handlers for more info on these variables.  Note
  ## that this_package is not included in the list (because we're
  ## calling it as a package method)
  sub attrDebug_1 {
    my $this_package   = shift();
    my $caller_package = shift();
    my $code_symbol    = shift();
    my $code_ref       = shift();
    my $atribute       = shift(); ## will be Debug ##
    my $attribute_data = shift();
    my $phase          = shift();
  
    ## lets see what comes in and out ##
    return sub {
      warn "IN TO ". scalar( *$code_symbol )
        . join "\n", @_;
      my @data = &code_ref(@_);
      warn "OUT FROM ". scalar( *$code_symbol )
        . join "\n", @data;
      return @data;
    }
  }
  
  sub ourTest_1 {
    my $message = shift();
  }
  
  1;
  
  ...
  ...
  
  ## now, in your code: test_me.pl
  
  
  sub my_funky_function : Debug {
    my $self = shift();
    my $var1 = shift();
    my $var2 = shift();
  
    ## do some stuff ##
    Debug( "VAR1: $var1" );
    Debug( "VAR2: $var2" );
  }
  
  ## since you've tied any debugging checks in to your env
  ## you can turn MyPackage functionality on or off by setting
  ## env vars with the special tag: DEBUG_PERL
  
  ## set it to level 1 for everything
  %> ALL_DEBUG_PERL=1 ./test_me.pl
  ## or
  %> DEBUG_PERL=1 ./test_me.pl
  
  ## just for package 'main'
  %> DEBUG_PERL_main=1 ./test_me.pl
  
  ## just for a single function
  %> DEBUG_PERL_main__my_funky_function ./test_me.pl
  
  ## force it off for everyone
  %> NO_DEBUG_PERL=1 ./test_me.pl

DESCRIPTION

Attribute::GlobalEnable provides switchable attribute hooks for all packages in your namespace. It's primarily been developed with the idea of providing debugging hooks that are very unobtrusive to the code. Since attributes trigger their functionality at compile time (or at the least very early on, before execution time), not enabling (or having your flags all off) does nothing to the code. All the special functionality will be skipped, and your code should operate like it wasn't there at all. It is, however, not specific to debugging, so you can do what you wish with your attributes.

Since all of the functionality of what your attributes do is defined by the user (you), you MUST subpackage Attribute::GlobalEnable. It handles all of the exporting for you, but you must format your hooks as explained below.

Along with the special attribute functionality, the package also builds special functions named the same as your attributes, and exports them to which ever package 'use's your sub-package. Along with this, you can define special flags that will turn this function on or off, and the flags play with the rest of the system as one would expect.

This package does not inherit from the Attribute class.

FUNCTIONS

There are no functions to use directly with this package. There are, however, some special function names that YOU will define when subpackaging this, and a package constructor where you do just that.

Package Constructor

This package is NOT an object. It is functional only. However, you must initialize the package for use. The package is (more or less) a singleton, so you can only initialize it once. DO NOT try to have multiple packages set values, as it will just skip subsequent attempts to import past the first one.

There are 2 required keys, and 1 optional:

(required) ENABLE_ATTR => $hash_ref

This key is really the meat of it all, and the data you supply initializes the attributes, and what functions it expects to see in your sub-package. The structure of the hash is laid out as:

  {'Attribute_name' => 'SPECIAL_KEY', 'Attribute_name_2'... }

The attribute name must be capitalized (see Attribute::Handlers), the SPECIAL_KEY can be any string. You can have as many key => value pairs as you deem necessary.

Setting this value has multiple effects. First, it assigns the attribute 'Attribute_name' to a subroutine in the callers namespace, named:

  attr'Attribute_name'_#
  ## ex: attrDebug_1

The # should be an integer, and represents the number the SPECIAL_KEY has been set to. More on that in a second tho. The attribute name is set in the UNIVERSAL namespace, so now it can be utilized by everything under your particular perl sun.

What ever packages 'use' your sub-package, have another special subroutine named 'Attribute_name' exported to their namespace. This subroutine points to your sub-package subroutine named (similarly to above):

  our'Attribute_name'_#
  ## ex: ourDebug_1

The # should be an integer (see below for proper values) This function can be turned on by the regular SPECIAL KEY, but also by any ENABLE_FLAGS that you've defined as well... but more on that later.

The 'SPECIAL_KEY' is the distinct identifier to trigger this attributes functionality. It is not really meant to be used on it's own, (but it can). It is mostly an identifier string that allows you to add stuff to it to easily customize what you want to see (or do or whatever). There are 2 special pre-strings that you can slap on to the begining of the key:

ALL_'SPECIAL_KEY' (or just 'SPECIAL_KEY')

This turns the attributes functionality on for ALL of those subroutines that have the attribute. This trumps all other settings, except for the NO_ pre-string.

NO_'SPECIAL_KEY'

This is essentially the default behaviour, turning the attribute stuff off. This trumps everything... Other 'SPECIAL_KEY's, and any ENABLE_FLAGS.

You can append package names, or even subroutines to the end of the 'SPECIAL_KEY', in order to turn the attribute functionality on for a specific package or subroutine. Just separate the 'SPECIAL_KEY' and your specific string with an underscore. Neato eh? There is one caveat to this. The regular perl package (namespace) separator is replaced with two underscores, so if you wanted to turn on attribute behaviour for MyPackage::ThisPackage, your key would look like so:

'SPECIAL_KEY'_MyPackage__ThisPacakge

I did this so that you can just pass in the %ENV hash, and set your attribute 'SPECIAL_KEY's on the command line or whathave you.

Finally, the '#'s that you must name each of your special subs with, represent a level for a particular functionality. This level is checked each time, and the appropriate subroutine will be called, or it will try the next level down. So, forexample: If you just have attr'Attribute_name'_1, but you set your 'SPECIAL_KEY' to 3, then attr'Attribute_name'_1 will be executed. if you had an attr'Attribute_name'_2, then that subroutine would be executed instead of 1. This will not call each subroutine as it goes, it simply executes the first one it finds.

(required) ENABLE_CHK => $hash_ref

This must be set to a hash ref whos structure is laid out as:

  SOME_FLAG => $integer,

$integer should be positive, and represents the attribute level you wish to do attribute stuff at. (see ENABLEL_ATTR above for more info on that). The actual hash can be empty, but the reference must exist.

This represents the actual user set triggers for the attributes. Telling GlobalEnable which to... well... enable, and which to skip.

See the previous section for a description on special characters etc...

ENABLE_FLAG => $hash_ref

The $hash_ref structure must be:

  { Attribute_name => [ list of flags ], Attribute_name_2 ... }

The ENABLE_FLAG is optional, and describes flags that can be set for the exported 'Attribute_name' subroutines. These are exported as global constants, so it looks nice and neat in your code. This essentially links that sub call to that flag. The flag is still set like it would normally be set in the ENABLE_CHK hash, however, you still must use the 'SPECIAL_KEY' (see above) in the assignment, so your assignment will look like:

  'SPECIAL_KEY'_'FLAG'

attr'Attribute_name'_#

See ENABLE_ATTR above for a description on the layout naming scheme for this particular subroutine name.

This is your attribute hook for a particular level. This must return a subroutine. The subroutine that it returns replaces the one the attribute is currently assigned to. You can do anything you wish at this point, as you'll have access to everything that's being passed in, everything that's being passed out, and whatever else you want.

It will always get these variables when it's called:

[0] : package name ala $package->attr'Attribute_name'_1
[1] : callers package name
[2] : the code symbol (GLOB)
[3] : the code reference of the sub that has this attribute turned on.
[4] : the attribute name that triggered this.
[5] : any attribute data assigned to the attribute.
[6] : the current phase this was activated in.

See perldoc Attribute::Handlers for more descirption on what these values are, or how to utilize them.

our'Attribute_name'_#

This is the sub that's pointed to from our exported 'Attribute_name' subroutine. If you pass in a valid flag, it'll clear that out before it sends the rest of the arguments your way. There is no need to return a sub, as this is the actual subroutine that's executed when you trigger this special sub.

EXAMPLES

For right now, see the tests for some examples. There's a test module in the test dir as well. I'll fill in some examples a little later.

SEE ALSO

perldoc perlsub, Attribute::Handlers

AUTHOR

Craig Monson (cmonson [at the following]malachiarts com)

ERRORS

Must specify some arguments.

You tried to init the package with nuttin. Gotta pass in some args.

Must sub-package

This isn't meant to be run on it's own.

ENABLE_CHK needs to be set with a hash ref for this module to be used

your ENABLE_CHK wasn't a hash ref. Please read this doc ;)

ENABLE_ATTR must be set with a ref to a hash containing attribute names => key name.

your ENABLE_ATTR was in the wrong format.

'blah' or 'blah' must be in valid format.

Your key or value for ENABLE_ATTR wasn't in the right format.

ENABLE_FLAG needs to be set with an array.

If you're gonna set ENABLE_FLAG, the values for the keys must be array refs.

Our eval failed: blah blah

If you get this, then it's prolly a bug in the package. Please report it to me.

BUGS

<none as of yet>

COPYRIGHT

I suppose I (Craig Monson) own it. All Rights Reserved. This module is 100% free software, and may be used, reused, redistributed, messed with, subclassed, deleted, printed, compiled, and pooped on, just so long as you follow the terms described by Perl itself.