Symbol-Get-0.12/000755 000766 000024 00000000000 14612001760 014023 5ustar00felipestaff000000 000000 Symbol-Get-0.12/LICENSE000644 000766 000024 00000001777 14611736610 015054 0ustar00felipestaff000000 000000 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Symbol-Get-0.12/Changes000644 000766 000024 00000001715 14612001632 015320 0ustar00felipestaff000000 000000 Revision history for Perl module Symbol::Get 0.12 Tue 23 Apr 2024 - Update license in Makefile.PL. (Thank you, @mavit!) 0.11 Tue 23 Apr 2024 - (No code changes.) - Remove Travis CI. - Change README to Markdown. - Re-license under the MIT License. 0.10 Fri 24 Aug 2018 - Fix LICENSE file (again) 0.09 Fri 24 Aug 2018 - Fix LICENSE file. 0.08 Thu 21 Sep 2017 - Fix SYNOPSIS to show correct usage. 0.07 Thu 09 Feb 2017 - Disown get() for constants. It’s just not reliable. 0.06 Wed 08 Feb 2017 - Add copy_constant() for more reliable access to constants. 0.05 Fri 23 Dec 2016 - Accommodate pre-5.20 Perl versions’ storage of list constants 0.04 Thu 22 Dec 2016 - Teach get() how to handle list constants 0.03 Wed 21 Dec 2016 - Teach get() how to handle constants 0.02 Tue 20 Dec 2016 - Add get_names(), and failure tests 0.01 Mon 19 Dec 2016 - original version; created by ExtUtils::ModuleMaker 0.55 Symbol-Get-0.12/MANIFEST000644 000766 000024 00000000404 14612001760 015152 0ustar00felipestaff000000 000000 Changes LICENSE MANIFEST Makefile.PL README.md lib/Symbol/Get.pm t/001_load.t t/002_usage.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) Symbol-Get-0.12/t/000755 000766 000024 00000000000 14612001757 014274 5ustar00felipestaff000000 000000 Symbol-Get-0.12/README.md000644 000766 000024 00000003223 14612001732 015301 0ustar00felipestaff000000 000000 # NAME Symbol::Get - Read Perl’s symbol table programmatically # SYNOPSIS package Foo; our $name = 'haha'; our @list = ( 1, 2, 3 ); our %hash = ( foo => 1, bar => 2 ); use constant my_const => 'haha'; use constant my_const_list => qw( a b c ); sub doit { ... } my $name_sr = Symbol::Get::get('$Foo::name'); # \$name my $list_ar = Symbol::Get::get('@Foo::list'); # \@list my $hash_hr = Symbol::Get::get('%Foo::hash'); $ \%hash #Defaults to __PACKAGE__ if none is given: my $doit_cr = Symbol::Get::get('&doit'); #Constants: my $const_val = Symbol::Get::copy_constant('Foo::my_const'); my @const_list = Symbol::Get::copy_constant('Foo::my_const_list'); #The below return the same results since get_names() defaults #to the current package if none is given. my @names = Symbol::Get::get_names('Foo'); # keys %Foo:: my @names = Symbol::Get::get_names(); # DESCRIPTION Occasionally I have need to reference a variable programmatically. This module facilitates that by providing an easy, syntactic-sugar-y, read-only interface to the symbol table. The SYNOPSIS above should pretty well cover usage. # ABOUT PERL CONSTANTS Previous versions of this module endorsed constructions like: my $const_sr = Symbol::Get::get('Foo::my_const'); my $const_ar = Symbol::Get::get('Foo::my_const_list'); … to read constants from the symbol table. This isn’t reliable across Perl versions, though, so don’t do it; instead, use `copy_constant()`. # SEE ALSO - [Symbol::Values](https://metacpan.org/pod/Symbol%3A%3AValues) # LICENSE This module is licensed under the MIT License. Symbol-Get-0.12/META.yml000644 000766 000024 00000001265 14612001760 015300 0ustar00felipestaff000000 000000 --- abstract: 'Read Perl’s symbol table programmatically' author: - 'Felipe Gasper (FELIPE)' build_requires: ExtUtils::MakeMaker: '0' Test::Deep: '0' Test::Exception: '0' Test::More: '0.44' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.62, CPAN::Meta::Converter version 2.150010' license: mit meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Symbol-Get no_index: directory: - t - inc requires: Call::Context: '0' resources: repository: https://github.com/FGasper/p5-Symbol-Get.git version: '0.12' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' Symbol-Get-0.12/lib/000755 000766 000024 00000000000 14612001757 014577 5ustar00felipestaff000000 000000 Symbol-Get-0.12/Makefile.PL000644 000766 000024 00000001551 14612001574 016002 0ustar00felipestaff000000 000000 use ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( NAME => 'Symbol::Get', VERSION_FROM => 'lib/Symbol/Get.pm', # finds \$VERSION AUTHOR => 'Felipe Gasper (FELIPE)', ABSTRACT_FROM => 'lib/Symbol/Get.pm', LICENSE => 'mit', META_MERGE => { 'meta-spec' => { version => 2 }, resources => { repository => { type => 'git', url => 'https://github.com/FGasper/p5-Symbol-Get.git', web => 'https://github.com/FGasper/p5-Symbol-Get', }, }, }, PREREQ_PM => { 'Call::Context' => 0, }, TEST_REQUIRES => { 'Test::More' => 0.44, 'Test::Deep' => 0, 'Test::Exception' => 0, }, ); Symbol-Get-0.12/META.json000644 000766 000024 00000002427 14612001760 015451 0ustar00felipestaff000000 000000 { "abstract" : "Read Perl’s symbol table programmatically", "author" : [ "Felipe Gasper (FELIPE)" ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.62, CPAN::Meta::Converter version 2.150010", "license" : [ "mit" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Symbol-Get", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Call::Context" : "0" } }, "test" : { "requires" : { "Test::Deep" : "0", "Test::Exception" : "0", "Test::More" : "0.44" } } }, "release_status" : "stable", "resources" : { "repository" : { "type" : "git", "url" : "https://github.com/FGasper/p5-Symbol-Get.git", "web" : "https://github.com/FGasper/p5-Symbol-Get" } }, "version" : "0.12", "x_serialization_backend" : "JSON::PP version 4.06" } Symbol-Get-0.12/lib/Symbol/000755 000766 000024 00000000000 14612001757 016044 5ustar00felipestaff000000 000000 Symbol-Get-0.12/lib/Symbol/Get.pm000644 000766 000024 00000010773 14612001646 017126 0ustar00felipestaff000000 000000 package Symbol::Get; use strict; use warnings; use Call::Context (); our $VERSION = '0.12'; =encoding utf-8 =head1 NAME Symbol::Get - Read Perl’s symbol table programmatically =head1 SYNOPSIS package Foo; our $name = 'haha'; our @list = ( 1, 2, 3 ); our %hash = ( foo => 1, bar => 2 ); use constant my_const => 'haha'; use constant my_const_list => qw( a b c ); sub doit { ... } my $name_sr = Symbol::Get::get('$Foo::name'); # \$name my $list_ar = Symbol::Get::get('@Foo::list'); # \@list my $hash_hr = Symbol::Get::get('%Foo::hash'); $ \%hash #Defaults to __PACKAGE__ if none is given: my $doit_cr = Symbol::Get::get('&doit'); #Constants: my $const_val = Symbol::Get::copy_constant('Foo::my_const'); my @const_list = Symbol::Get::copy_constant('Foo::my_const_list'); #The below return the same results since get_names() defaults #to the current package if none is given. my @names = Symbol::Get::get_names('Foo'); # keys %Foo:: my @names = Symbol::Get::get_names(); =head1 DESCRIPTION Occasionally I have need to reference a variable programmatically. This module facilitates that by providing an easy, syntactic-sugar-y, read-only interface to the symbol table. The SYNOPSIS above should pretty well cover usage. =head1 ABOUT PERL CONSTANTS Previous versions of this module endorsed constructions like: my $const_sr = Symbol::Get::get('Foo::my_const'); my $const_ar = Symbol::Get::get('Foo::my_const_list'); … to read constants from the symbol table. This isn’t reliable across Perl versions, though, so don’t do it; instead, use C. =head1 SEE ALSO =over 4 =item * L =back =head1 LICENSE This module is licensed under the MIT License. =cut use constant MIN_LIST_CONSTANT_PERL_VERSION => v5.20.0; my %_sigil_to_type = qw( $ SCALAR @ ARRAY % HASH & CODE ); my $sigils_re_txt = join('|', keys %_sigil_to_type); sub get { my ($var) = @_; die 'Need a variable or constant name!' if !length $var; my $sigil = substr($var, 0, 1); goto \&_get_constant if $sigil =~ tr<>; my $type = $_sigil_to_type{$sigil} or die "Unrecognized sigil: “$sigil”"; my $table_hr = _get_table_hr( substr($var, 1) ); return $table_hr && *{$table_hr}{$type}; } sub copy_constant { my ($var) = @_; my $ref = _get_table_hr($var); my @value; if ('SCALAR' eq ref $ref) { @value = ($$ref); } elsif ('ARRAY' eq ref $ref) { @value = @$ref; } else { @value = *{$ref}{'CODE'}->(); } if (@value > 1) { Call::Context::must_be_list(); return @value; } return $value[0]; } #Referenced in tests. sub _perl_supports_getting_list_constant_ref { return $^V ge MIN_LIST_CONSTANT_PERL_VERSION() } sub _get_constant { my ($var) = @_; my $ref = _get_table_hr($var); if ('SCALAR' ne ref($ref) && 'ARRAY' ne ref($ref)) { my $msg = "$var is a regular symbol table entry, not a constant."; if ( !_perl_supports_getting_list_constant_ref() ) { $msg .= " Your Perl version ($^V) stores list constants in the symbol table as CODE references rather than ARRAYs; maybe that’s the issue?"; } die $msg; } return $ref; } sub get_names { my ($module) = @_; $module ||= (caller 0)[0]; Call::Context::must_be_list(); my $table_hr = _get_module_table_hr($module); die "Unknown namespace: “$module”" if !$table_hr; return keys %$table_hr; } #---------------------------------------------------------------------- # To be completed if needed: # #sub list_sigils { # my ($full_name) = @_; # # Call::Context::must_be_list(); # # my ($module, $name) = ($full_name =~ m<(?:(.+)::)?(.+)>); # # my $table_hr = _get_table_for_module_name($module); # my $glob = *{$table_hr}; # # return #} # #---------------------------------------------------------------------- sub _get_module_table_hr { my ($module) = @_; my @nodes = split m<::>, $module; my $table_hr = \%main::; my $pkg = q<>; for my $n (@nodes) { $table_hr = $table_hr->{"$n\::"}; $pkg .= "$n\::"; } return $table_hr; } sub _get_table_hr { my ($name) = @_; $name =~ m<\A (?: (.+) ::)? ([^:]+ (?: ::)?) \z>x or do { die "Invalid variable name: “$name”"; }; my $module = $1 || (caller 1)[0]; my $table_hr = _get_module_table_hr($module); return $table_hr->{$2}; } 1; Symbol-Get-0.12/t/002_usage.t000644 000766 000024 00000010643 13047237622 016155 0ustar00felipestaff000000 000000 package t::usage; use strict; use warnings; use Test::More; use Test::Deep; use Test::Exception; use constant MIN_SCALAR_CONSTANT_PERL_VERSION => v5.10.0; plan tests => 16; use Symbol::Get (); sub _perl_supports_getting_scalar_constant_ref { return $^V ge MIN_SCALAR_CONSTANT_PERL_VERSION } #---------------------------------------------------------------------- package t::Foo::Bar; use Test::More (); use Test::Deep; #use Test::Exception; use constant my_const => 'haha'; use constant my_list => qw( ha ha ); our $thing = 'thing'; our @list = qw( a b c ); our %hash = ( a => 1, b => 2 ); sub my_code { } #---------------------------------------------------------------------- package t::usage; is( Symbol::Get::get('$t::Foo::Bar::thing'), \$t::Foo::Bar::thing, 'scalar', ); is( Symbol::Get::get('@t::Foo::Bar::list'), \@t::Foo::Bar::list, 'list', ); is( Symbol::Get::get('%t::Foo::Bar::hash'), \%t::Foo::Bar::hash, 'hash', ); is( Symbol::Get::get('%t::Foo::Bar::'), \%t::Foo::Bar::, 'symbol table hash', ); is( Symbol::Get::get('&t::Foo::Bar::my_code'), \&t::Foo::Bar::my_code, 'code', ); is( Symbol::Get::get('&t::Foo::Bar::i_am_not_there'), undef, 'get() returns undef on an unknown variable name', ); #---------------------------------------------------------------------- #SKIP: { # skip 'Needs >= v5.10', 1 if !_perl_supports_getting_scalar_constant_ref(); # # is( # Symbol::Get::get('t::Foo::Bar::my_const'), # $t::Foo::Bar::{'my_const'}, # 'constant (scalar)', # ); #} # #is( # Symbol::Get::copy_constant('t::Foo::Bar::my_const'), # t::Foo::Bar::my_const(), # 'copy_constant (scalar, no package)', #); # #SKIP: { # skip 'Needs >= v5.20', 1 if !Symbol::Get::_perl_supports_getting_list_constant_ref(); # # is( # Symbol::Get::get('t::Foo::Bar::my_list'), # $t::Foo::Bar::{'my_list'}, # 'constant (array)', # ); #} # #throws_ok( # sub { diag explain Symbol::Get::get('t::Foo::Bar::list') }, # qr, # 'constant die()s if fed a non-constant', #); is_deeply( [ Symbol::Get::copy_constant('t::Foo::Bar::my_list') ], [ t::Foo::Bar::my_list() ], 'copy_constant (list, no package)', ); throws_ok( sub { my $v = Symbol::Get::copy_constant('t::Foo::Bar::my_list') }, 'Call::Context::X', 'copy_constant() demands list context for a list', ); #---------------------------------------------------------------------- #cmp_deeply( # [ Symbol::Get::get_names('t::Foo::Bar') ], # superbagof( qw( thing list hash my_code my_const my_list ) ), # 'get_names()', #) or diag explain [ Symbol::Get::get_names('t::Foo::Bar') ]; # #throws_ok( # sub { () = Symbol::Get::get_names('t::Foo::Bar::NOT_THERE') }, # qr, # 'get_names() throws on an unknown package name', #); #---------------------------------------------------------------------- package t::Foo::Bar; use Test::More; use Test::Exception; is( Symbol::Get::get('$thing'), \$t::Foo::Bar::thing, 'scalar, no package', ); is( Symbol::Get::get('@list'), \@t::Foo::Bar::list, 'list, no package', ); is( Symbol::Get::get('%hash'), \%t::Foo::Bar::hash, 'hash, no package', ); is( Symbol::Get::get('&my_code'), \&t::Foo::Bar::my_code, 'code, no package', ); cmp_deeply( [ Symbol::Get::get_names() ], superbagof( qw( thing list hash my_code my_const my_list ) ), 'get_names(), no package', ) or diag explain [ Symbol::Get::get_names('t::Foo::Bar') ]; #SKIP: { # Test::More::skip 'Needs >= v5.10', 1 if !t::usage::_perl_supports_getting_scalar_constant_ref(); # # is( # Symbol::Get::get('my_const'), # $t::Foo::Bar::{'my_const'}, # 'constant (scalar, no package)', # ); #} is( Symbol::Get::copy_constant('my_const'), t::Foo::Bar::my_const(), 'copy_constant (scalar, no package)', ); #SKIP: { # skip 'Needs >= v5.20', 1 if !Symbol::Get::_perl_supports_getting_list_constant_ref(); # # is( # Symbol::Get::get('my_list'), # $t::Foo::Bar::{'my_list'}, # 'constant (array, no package)', # ); #} is_deeply( [ Symbol::Get::copy_constant('my_list') ], [ t::Foo::Bar::my_list() ], 'copy_constant (list, no package)', ); throws_ok( sub { my $v = Symbol::Get::copy_constant('my_list') }, 'Call::Context::X', 'copy_constant() demands list context for a list', ); 1; Symbol-Get-0.12/t/001_load.t000644 000766 000024 00000000223 13026130566 015754 0ustar00felipestaff000000 000000 # -*- perl -*- # t/001_load.t - check module loading and create testing directory use Test::More tests => 1; BEGIN { use_ok( 'Symbol::Get' ); }