diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2014-10-04 17:35:57 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2014-10-04 17:35:57 +0000 |
commit | a3341f774a4aa00765970301e259be818929a7cf (patch) | |
tree | f59eaff8b72b2ad1090f8ff3b8be4c89536db204 | |
download | Exporter-Tiny-tarball-a3341f774a4aa00765970301e259be818929a7cf.tar.gz |
Exporter-Tiny-0.042HEADExporter-Tiny-0.042master
-rw-r--r-- | CONTRIBUTING | 83 | ||||
-rw-r--r-- | COPYRIGHT | 65 | ||||
-rw-r--r-- | CREDITS | 6 | ||||
-rw-r--r-- | Changes | 108 | ||||
-rw-r--r-- | INSTALL | 38 | ||||
-rw-r--r-- | LICENSE | 379 | ||||
-rw-r--r-- | MANIFEST | 27 | ||||
-rw-r--r-- | META.json | 76 | ||||
-rw-r--r-- | META.yml | 41 | ||||
-rw-r--r-- | Makefile.PL | 144 | ||||
-rw-r--r-- | README | 421 | ||||
-rw-r--r-- | SIGNATURE | 49 | ||||
-rw-r--r-- | dist.ini | 3 | ||||
-rw-r--r-- | doap.ttl | 348 | ||||
-rw-r--r-- | examples/Example/Exporter.pm | 56 | ||||
-rw-r--r-- | lib/Exporter/Shiny.pm | 111 | ||||
-rw-r--r-- | lib/Exporter/Tiny.pm | 833 | ||||
-rw-r--r-- | t/01basic.t | 38 | ||||
-rw-r--r-- | t/02renaming.t | 50 | ||||
-rw-r--r-- | t/03generators.t | 38 | ||||
-rw-r--r-- | t/04into.t | 36 | ||||
-rw-r--r-- | t/05shiny.t | 40 | ||||
-rw-r--r-- | t/06notwant.t | 41 | ||||
-rw-r--r-- | t/07regexp.t | 48 | ||||
-rw-r--r-- | t/08tags.t | 66 | ||||
-rw-r--r-- | t/09warnings.t | 83 | ||||
-rw-r--r-- | t/10no.t | 54 |
27 files changed, 3282 insertions, 0 deletions
diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 0000000..ba115b4 --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,83 @@ +NAME + CONTRIBUTING + +DESCRIPTION + If you're reading this document, that means you might be thinking about + helping me out with this project. Thanks! + + Here's some ways you could help out: + + * Bug reports + + Found a bug? Great! (Well, not so great I suppose.) + + The place to report them is <https://rt.cpan.org/>. Don't e-mail me + about it, as your e-mail is more than likely to get lost amongst the + spam. + + An example script clearly demonstrating the bug (preferably written + using Test::More) would be greatly appreciated. + + * Patches + + If you've found a bug and written a fix for it, even better! + + Generally speaking you should check out the latest copy of the code + from the source repository rather than using the CPAN distribution. + The file META.yml should contain a link to the source repository. If + not, then try <https://github.com/tobyink> or submit a bug report. + (As far as I'm concerned the lack of a link is a bug.) Many of my + distributions are also mirrored at <https://bitbucket.org/tobyink>. + + To submit the patch, do a pull request on GitHub or Bitbucket, or + attach a diff file to a bug report. Unless otherwise stated, I'll + assume that your contributions are licensed under the same terms as + the rest of the project. + + (If using git, feel free to work in a branch. For Mercurial, I'd + prefer bookmarks within the default branch.) + + * Documentation + + If there's anything unclear in the documentation, please submit this + as a bug report or patch as above. + + Non-toy example scripts that I can bundle would also be appreciated. + + * Translation + + Translations of documentation would be welcome. + + For translations of error messages and other strings embedded in the + code, check with me first. Sometimes the English strings may not in + a stable state, so it would be a waste of time translating them. + + Coding Style + I tend to write using something approximating the Allman style, using + tabs for indentation and Unix-style line breaks. + + * <http://en.wikipedia.org/wiki/Indent_style#Allman_style> + + * <http://www.derkarl.org/why_to_tabs.html> + + I nominally encode all source files as UTF-8, though in practice most of + them use a 7-bit-safe ASCII-compatible subset of UTF-8. + +AUTHOR + Toby Inkster <tobyink@cpan.org>. + +COPYRIGHT AND LICENCE + Copyright (c) 2012-2014 by Toby Inkster. + + CONTRIBUTING is available under three different licences permitting its + redistribution: the CC-BY-SA_UK-2.0 licence, plus the same licences as + Perl itself, which is distributed under the GNU General Public Licence + version 1, and the Artistic Licence. + + This file is licensed under the Creative Commons Attribution-ShareAlike + 2.0 UK: England & Wales License. To view a copy of this license, visit + <http://creativecommons.org/licenses/by-sa/2.0/uk/>. + + This file is free software; you can redistribute it and/or modify it + under the same terms as the Perl 5 programming language system itself. + diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..a25d300 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,65 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Exporter-Tiny +Upstream-Contact: Toby Inkster (TOBYINK) <tobyink@cpan.org> +Source: https://metacpan.org/release/Exporter-Tiny + +Files: lib/Exporter/Shiny.pm + t/05shiny.t + t/06notwant.t + t/07regexp.t + t/08tags.t + t/09warnings.t + t/10no.t +Copyright: This software is copyright (c) 2014 by Toby Inkster. +License: GPL-1.0+ or Artistic-1.0 + +Files: Changes + META.json + META.yml + doap.ttl +Copyright: Copyright 2014 Toby Inkster. +License: GPL-1.0+ or Artistic-1.0 + +Files: CONTRIBUTING + INSTALL + LICENSE + examples/Example/Exporter.pm +Copyright: Unknown +License: Unknown + +Files: t/01basic.t + t/02renaming.t + t/03generators.t + t/04into.t +Copyright: This software is copyright (c) 2013 by Toby Inkster. +License: GPL-1.0+ or Artistic-1.0 + +Files: COPYRIGHT + CREDITS + SIGNATURE +Copyright: None +License: public-domain + +Files: README + lib/Exporter/Tiny.pm +Copyright: This software is copyright (c) 2013-2014 by Toby Inkster. +License: GPL-1.0+ or Artistic-1.0 + +Files: Makefile.PL + dist.ini +Copyright: Copyright 2013 Toby Inkster. +License: GPL-1.0+ or Artistic-1.0 + +License: Artistic-1.0 + This software is Copyright (c) 2014 by the copyright holder(s). + + This is free software, licensed under: + + The Artistic License 1.0 + +License: GPL-1.0 + This software is Copyright (c) 2014 by the copyright holder(s). + + This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 @@ -0,0 +1,6 @@ +Maintainer: +- Toby Inkster (TOBYINK) <tobyink@cpan.org> + +Thanks: +- CHOCOLATEBOY <chocolateboy@cpan.org> + @@ -0,0 +1,108 @@ +Exporter-Tiny +============= + +Created: 2013-09-05 +Home page: <https://metacpan.org/release/Exporter-Tiny> +Bug tracker: <http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny> +Maintainer: Toby Inkster (TOBYINK) <tobyink@cpan.org> + +0.042 2014-10-04 + + [ Documentation ] + - Document the warning emitted when you provide options to a function you + are unimporting. + + [ Other ] + - Housekeeping on %TRACKED. + +0.041_02 2014-09-19 + + [ Bug Fixes ] + - Option validation needs to happen after expanding tags. + +0.041_01 2014-09-18 + + - Add an `unimport` feature. + +0.040 2014-09-17 + + [ Packaging ] + - Repackage as a stable release. + +0.039_01 2014-07-20 + + [ Documentation ] + - Document warning and error messages produced by Exporter::Tiny. + + [ Other ] + - Exporter::Tiny would previously cause B.pm to be loaded into memory any + time it exported anything. It no longer does. + - No longer die when redefining locally defined subs. + - Warn when redefining any subs. + +0.038 2014-04-04 + +0.037_03 2014-04-02 + + [ Bug Fixes ] + - Only attempt to merge hashes if we're sure they're both really hashes! + +0.037_02 2014-04-02 + + - Improved handling of hashrefs of options passed to tags, and hashrefs of + options found within %EXPORT_TAGS arrayrefs. + +0.037_01 2014-03-26 + + [ Documentation ] + - Fix minor error in documentation of generators. + + [ Other ] + - Added: Support Exporter.pm's import negation syntax qw( !foo ). + - Added: Support Exporter.pm's regexp import syntax qw( /foo/ ). + +0.036 2014-03-11 + +0.035_02 2014-03-01 + + [ Documentation ] + - Document exactly what Exporter::Shiny is supposed to do. + + [ Test Suite ] + - Make t/02renaming.t less noisy. + +0.035_01 2014-03-01 + + [ Packaging ] + - Explicitly list minimum Perl version: 5.6.1. + +0.034 2014-01-19 + +0.033_01 2014-01-19 + + - Added: Add a new wrapper module called Exporter::Shiny. + +0.032 2013-12-30 + +0.031_01 2013-12-30 + + [ Test Suite ] + - No longer require a recent version of Test::More; the Test::More bundled + with Perl 5.6.2 should suffice. + +0.030 2013-09-26 + + [ Test Suite ] + - Test for the 'into' option. + +0.029_01 2013-09-26 + + [ Documentation ] + - Exporter::TypeTiny is being retired, so modify documentation and + distribution metadata for Exporter::Tiny to no longer point there. + +0.026 2013-09-05 Initial release + + [ Packaging ] + - Split Exporter::Tiny out from Exporter::TypeTiny. + CHOCOLATEBOY++ @@ -0,0 +1,38 @@ + Installing Exporter-Tiny should be straightforward. + +INSTALLATION WITH CPANMINUS + If you have cpanm, you only need one line: + + % cpanm Exporter::Tiny + + If you are installing into a system-wide directory, you may need to pass + the "-S" flag to cpanm, which uses sudo to install the module: + + % cpanm -S Exporter::Tiny + +INSTALLATION WITH THE CPAN SHELL + Alternatively, if your CPAN shell is set up, you should just be able to + do: + + % cpan Exporter::Tiny + +MANUAL INSTALLATION + As a last resort, you can manually install it. Download the tarball and + unpack it. + + Consult the file META.json for a list of pre-requisites. Install these + first. + + To build Exporter-Tiny: + + % perl Makefile.PL + % make && make test + + Then install it: + + % make install + + If you are installing into a system-wide directory, you may need to run: + + % sudo make install + @@ -0,0 +1,379 @@ +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +Terms of the Perl programming language system itself + +a) the GNU General Public License as published by the Free + Software Foundation; either version 1, or (at your option) any + later version, or +b) the "Artistic License" + +--- The GNU General Public License, Version 1, February 1989 --- + +This software is Copyright (c) 2014 by Toby Inkster. + +This is free software, licensed under: + + The GNU General Public License, Version 1, February 1989 + + GNU GENERAL PUBLIC LICENSE + Version 1, February 1989 + + Copyright (C) 1989 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The license agreements of most software companies try to keep users +at the mercy of those companies. By contrast, our General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. The +General Public License applies to the Free Software Foundation's +software and to any other program whose authors commit to using it. +You can use it for your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Specifically, the General Public License is designed to make +sure that you have the freedom to give away or sell copies of free +software, that you receive source code or can get it if you want it, +that you can change the software or use pieces of it in new free +programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of a such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must tell them their rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any program or other work which +contains a notice placed by the copyright holder saying it may be +distributed under the terms of this General Public License. The +"Program", below, refers to any such program or work, and a "work based +on the Program" means either the Program or any work containing the +Program or a portion of it, either verbatim or with modifications. Each +licensee is addressed as "you". + + 1. You may copy and distribute verbatim copies of the Program's source +code as you receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice and +disclaimer of warranty; keep intact all the notices that refer to this +General Public License and to the absence of any warranty; and give any +other recipients of the Program a copy of this General Public License +along with the Program. You may charge a fee for the physical act of +transferring a copy. + + 2. You may modify your copy or copies of the Program or any portion of +it, and copy and distribute such modifications under the terms of Paragraph +1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating that + you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, that + in whole or in part contains the Program or any part thereof, either + with or without modifications, to be licensed at no charge to all + third parties under the terms of this General Public License (except + that you may choose to grant warranty protection to some or all + third parties, at your option). + + c) If the modified program normally reads commands interactively when + run, you must cause it, when started running for such interactive use + in the simplest and most usual way, to print or display an + announcement including an appropriate copyright notice and a notice + that there is no warranty (or else, saying that you provide a + warranty) and that users may redistribute the program under these + conditions, and telling the user how to view a copy of this General + Public License. + + d) You may charge a fee for the physical act of transferring a + copy, and you may at your option offer warranty protection in + exchange for a fee. + +Mere aggregation of another independent work with the Program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other work under the scope of these terms. + + 3. You may copy and distribute the Program (or a portion or derivative of +it, under Paragraph 2) in object code or executable form under the terms of +Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal charge + for the cost of distribution) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +Source code for a work means the preferred form of the work for making +modifications to it. For an executable file, complete source code means +all the source code for all modules it contains; but, as a special +exception, it need not include source code for modules which are standard +libraries that accompany the operating system on which the executable +file runs, or for standard header files or definitions files that +accompany that operating system. + + 4. You may not copy, modify, sublicense, distribute or transfer the +Program except as expressly provided under this General Public License. +Any attempt otherwise to copy, modify, sublicense, distribute or transfer +the Program is void, and will automatically terminate your rights to use +the Program under this License. However, parties who have received +copies, or rights to use copies, from you under this General Public +License will not have their licenses terminated so long as such parties +remain in full compliance. + + 5. By copying, distributing or modifying the Program (or any work based +on the Program) you indicate your acceptance of this license to do so, +and all its terms and conditions. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the original +licensor to copy, distribute or modify the Program subject to these +terms and conditions. You may not impose any further restrictions on the +recipients' exercise of the rights granted herein. + + 7. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of the license which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +the license, you may choose any version ever published by the Free Software +Foundation. + + 8. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to humanity, the best way to achieve this is to make it +free software which everyone can redistribute and change under these +terms. + + To do so, attach the following notices to the program. It is safest to +attach them to the start of each source file to most effectively convey +the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) 19yy <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19xx name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the +appropriate parts of the General Public License. Of course, the +commands you use may be called something other than `show w' and `show +c'; they could even be mouse-clicks or menu items--whatever suits your +program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + program `Gnomovision' (a program to direct compilers to make passes + at assemblers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +That's all there is to it! + + +--- The Artistic License 1.0 --- + +This software is Copyright (c) 2014 by Toby Inkster. + +This is free software, licensed under: + + The Artistic License 1.0 + +The Artistic License + +Preamble + +The intent of this document is to state the conditions under which a Package +may be copied, such that the Copyright Holder maintains some semblance of +artistic control over the development of the package, while giving the users of +the package the right to use and distribute the Package in a more-or-less +customary fashion, plus the right to make reasonable modifications. + +Definitions: + + - "Package" refers to the collection of files distributed by the Copyright + Holder, and derivatives of that collection of files created through + textual modification. + - "Standard Version" refers to such a Package if it has not been modified, + or has been modified in accordance with the wishes of the Copyright + Holder. + - "Copyright Holder" is whoever is named in the copyright or copyrights for + the package. + - "You" is you, if you're thinking about copying or distributing this Package. + - "Reasonable copying fee" is whatever you can justify on the basis of media + cost, duplication charges, time of people involved, and so on. (You will + not be required to justify it to the Copyright Holder, but only to the + computing community at large as a market that must bear the fee.) + - "Freely Available" means that no fee is charged for the item itself, though + there may be fees involved in handling the item. It also means that + recipients of the item may redistribute it under the same conditions they + received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications derived +from the Public Domain or from the Copyright Holder. A Package modified in such +a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided that +you insert a prominent notice in each changed file stating how and when you +changed that file, and provided that you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or an + equivalent medium, or placing the modifications on a major archive site + such as ftp.uu.net, or by allowing the Copyright Holder to include your + modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict with + standard executables, which must also be provided, and provide a separate + manual page for each non-standard executable that clearly documents how it + differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or executable +form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where to + get the Standard Version. + + b) accompany the distribution with the machine-readable source of the Package + with your modifications. + + c) accompany any non-standard executables with their corresponding Standard + Version executables, giving the non-standard executables non-standard + names, and clearly documenting the differences in manual pages (or + equivalent), together with instructions on where to get the Standard + Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. You +may not charge a fee for this Package itself. However, you may distribute this +Package in aggregate with other (possibly commercial) programs as part of a +larger (possibly commercial) software distribution provided that you do not +advertise this Package as a product of your own. + +6. The scripts and library files supplied as input to or produced as output +from the programs of this Package do not automatically fall under the copyright +of this Package, but belong to whomever generated them, and may be sold +commercially, and may be aggregated with this Package. + +7. C or perl subroutines supplied by you and linked into this Package shall not +be considered part of this Package. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +The End + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..26d4441 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,27 @@ +CONTRIBUTING +COPYRIGHT +CREDITS +Changes +INSTALL +LICENSE +MANIFEST +META.json +META.yml +Makefile.PL +README +SIGNATURE +dist.ini +doap.ttl +examples/Example/Exporter.pm +lib/Exporter/Shiny.pm +lib/Exporter/Tiny.pm +t/01basic.t +t/02renaming.t +t/03generators.t +t/04into.t +t/05shiny.t +t/06notwant.t +t/07regexp.t +t/08tags.t +t/09warnings.t +t/10no.t diff --git a/META.json b/META.json new file mode 100644 index 0000000..79ece81 --- /dev/null +++ b/META.json @@ -0,0 +1,76 @@ +{ + "abstract" : "an exporter with the features of Sub::Exporter but only core dependencies", + "author" : [ + "Toby Inkster (TOBYINK) <tobyink@cpan.org>" + ], + "dynamic_config" : 0, + "generated_by" : "Dist::Inkt::Profile::TOBYINK version 0.023, CPAN::Meta::Converter version 2.140640", + "keywords" : [], + "license" : [ + "perl_5" + ], + "meta-spec" : { + "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + "version" : "2" + }, + "name" : "Exporter-Tiny", + "no_index" : { + "directory" : [ + "eg", + "examples", + "inc", + "t", + "xt" + ] + }, + "optional_features" : {}, + "prereqs" : { + "configure" : { + "requires" : { + "ExtUtils::MakeMaker" : "6.17" + } + }, + "runtime" : { + "requires" : { + "perl" : "5.006001" + } + }, + "test" : { + "recommends" : { + "Test::Fatal" : "0", + "Test::Warnings" : "0" + }, + "requires" : { + "Test::More" : "0.47" + } + } + }, + "provides" : { + "Exporter::Shiny" : { + "file" : "lib/Exporter/Shiny.pm", + "version" : "0.042" + }, + "Exporter::Tiny" : { + "file" : "lib/Exporter/Tiny.pm", + "version" : "0.042" + } + }, + "release_status" : "stable", + "resources" : { + "bugtracker" : { + "web" : "http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny" + }, + "homepage" : "https://metacpan.org/release/Exporter-Tiny", + "license" : [ + "http://dev.perl.org/licenses/" + ], + "repository" : { + "type" : "git", + "url" : "git://github.com/tobyink/p5-exporter-tiny.git", + "web" : "https://github.com/tobyink/p5-exporter-tiny" + }, + "x_IRC" : "irc://irc.perl.org/#moops", + "x_identifier" : "http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/project" + }, + "version" : "0.042" +} diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..d83f602 --- /dev/null +++ b/META.yml @@ -0,0 +1,41 @@ +--- +abstract: 'an exporter with the features of Sub::Exporter but only core dependencies' +author: + - 'Toby Inkster (TOBYINK) <tobyink@cpan.org>' +build_requires: + Test::More: '0.47' +configure_requires: + ExtUtils::MakeMaker: '6.17' +dynamic_config: 0 +generated_by: 'Dist::Inkt::Profile::TOBYINK version 0.023, CPAN::Meta::Converter version 2.140640' +keywords: [] +license: perl +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: '1.4' +name: Exporter-Tiny +no_index: + directory: + - eg + - examples + - inc + - t + - xt +optional_features: {} +provides: + Exporter::Shiny: + file: lib/Exporter/Shiny.pm + version: '0.042' + Exporter::Tiny: + file: lib/Exporter/Tiny.pm + version: '0.042' +requires: + perl: '5.006001' +resources: + IRC: irc://irc.perl.org/#moops + Identifier: http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/project + bugtracker: http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny + homepage: https://metacpan.org/release/Exporter-Tiny + license: http://dev.perl.org/licenses/ + repository: git://github.com/tobyink/p5-exporter-tiny.git +version: '0.042' diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..4578ac2 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,144 @@ +use strict; +use ExtUtils::MakeMaker 6.17; + +my $EUMM = eval( $ExtUtils::MakeMaker::VERSION ); + +my $meta = { + "abstract" => "an exporter with the features of Sub::Exporter but only core dependencies", + "author" => ["Toby Inkster (TOBYINK) <tobyink\@cpan.org>"], + "dynamic_config" => 0, + "generated_by" => "Dist::Inkt::Profile::TOBYINK version 0.023, CPAN::Meta::Converter version 2.140640", + "keywords" => [], + "license" => ["perl_5"], + "meta-spec" => { + url => "http://search.cpan.org/perldoc?CPAN::Meta::Spec", + version => 2, + }, + "name" => "Exporter-Tiny", + "no_index" => { directory => ["eg", "examples", "inc", "t", "xt"] }, + "prereqs" => { + configure => { requires => { "ExtUtils::MakeMaker" => 6.17 } }, + runtime => { requires => { perl => 5.006001 } }, + test => { + recommends => { "Test::Fatal" => 0, "Test::Warnings" => 0 }, + requires => { "Test::More" => 0.47 }, + }, + }, + "provides" => { + "Exporter::Shiny" => { file => "lib/Exporter/Shiny.pm", version => 0.042 }, + "Exporter::Tiny" => { file => "lib/Exporter/Tiny.pm", version => 0.042 }, + }, + "release_status" => "stable", + "resources" => { + bugtracker => { + web => "http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny", + }, + homepage => "https://metacpan.org/release/Exporter-Tiny", + license => ["http://dev.perl.org/licenses/"], + repository => { + type => "git", + url => "git://github.com/tobyink/p5-exporter-tiny.git", + web => "https://github.com/tobyink/p5-exporter-tiny", + }, + x_identifier => "http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/project", + x_IRC => "irc://irc.perl.org/#moops", + }, + "version" => 0.042, +}; + +my %dynamic_config; + +my %WriteMakefileArgs = ( + ABSTRACT => $meta->{abstract}, + AUTHOR => ($EUMM >= 6.5702 ? $meta->{author} : $meta->{author}[0]), + DISTNAME => $meta->{name}, + VERSION => $meta->{version}, + EXE_FILES => [ map $_->{file}, values %{ $meta->{x_provides_scripts} || {} } ], + NAME => do { my $n = $meta->{name}; $n =~ s/-/::/g; $n }, + test => { TESTS => "t/*.t" }, + %dynamic_config, +); + +$WriteMakefileArgs{LICENSE} = $meta->{license}[0] if $EUMM >= 6.3001; + +sub deps +{ + my %r; + for my $stage (@_) + { + for my $dep (keys %{$meta->{prereqs}{$stage}{requires}}) + { + next if $dep eq 'perl'; + my $ver = $meta->{prereqs}{$stage}{requires}{$dep}; + $r{$dep} = $ver if !exists($r{$dep}) || $ver >= $r{$dep}; + } + } + \%r; +} + +my ($build_requires, $configure_requires, $runtime_requires, $test_requires); +if ($EUMM >= 6.6303) +{ + $WriteMakefileArgs{BUILD_REQUIRES} ||= deps('build'); + $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); + $WriteMakefileArgs{TEST_REQUIRES} ||= deps('test'); + $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime'); +} +elsif ($EUMM >= 6.5503) +{ + $WriteMakefileArgs{BUILD_REQUIRES} ||= deps('build', 'test'); + $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); + $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime'); +} +elsif ($EUMM >= 6.52) +{ + $WriteMakefileArgs{CONFIGURE_REQUIRES} ||= deps('configure'); + $WriteMakefileArgs{PREREQ_PM} ||= deps('runtime', 'build', 'test'); +} +else +{ + $WriteMakefileArgs{PREREQ_PM} ||= deps('configure', 'build', 'test', 'runtime'); +} + +{ + my ($minperl) = reverse sort( + grep defined && /^[0-9]+(\.[0-9]+)?$/, + map $meta->{prereqs}{$_}{requires}{perl}, + qw( configure build runtime ) + ); + + if (defined($minperl)) + { + die "Installing $meta->{name} requires Perl >= $minperl" + unless $] >= $minperl; + + $WriteMakefileArgs{MIN_PERL_VERSION} ||= $minperl + if $EUMM >= 6.48; + } +} + +sub FixMakefile +{ + return unless -d 'inc'; + my $file = shift; + + local *MAKEFILE; + open MAKEFILE, "< $file" or die "FixMakefile: Couldn't open $file: $!; bailing out"; + my $makefile = do { local $/; <MAKEFILE> }; + close MAKEFILE or die $!; + + $makefile =~ s/\b(test_harness\(\$\(TEST_VERBOSE\), )/$1'inc', /; + $makefile =~ s/( -I\$\(INST_ARCHLIB\))/ -Iinc$1/g; + $makefile =~ s/( "-I\$\(INST_LIB\)")/ "-Iinc"$1/g; + $makefile =~ s/^(FULLPERL = .*)/$1 "-Iinc"/m; + $makefile =~ s/^(PERL = .*)/$1 "-Iinc"/m; + + open MAKEFILE, "> $file" or die "FixMakefile: Couldn't open $file: $!; bailing out"; + print MAKEFILE $makefile or die $!; + close MAKEFILE or die $!; +} + +my $mm = WriteMakefile(%WriteMakefileArgs); +FixMakefile($mm->{FIRST_MAKEFILE} || 'Makefile'); +exit(0); + @@ -0,0 +1,421 @@ +NAME + Exporter::Tiny - an exporter with the features of Sub::Exporter but only + core dependencies + +SYNOPSIS + package MyUtils; + use base "Exporter::Tiny"; + our @EXPORT = qw(frobnicate); + sub frobnicate { my $n = shift; ... } + 1; + + package MyScript; + use MyUtils "frobnicate" => { -as => "frob" }; + print frob(42); + exit; + +DESCRIPTION + Exporter::Tiny supports many of Sub::Exporter's external-facing features + including renaming imported functions with the `-as`, `-prefix` and + `-suffix` options; explicit destinations with the `into` option; and + alternative installers with the `installler` option. But it's written in + only about 40% as many lines of code and with zero non-core dependencies. + + Its internal-facing interface is closer to Exporter.pm, with configuration + done through the @EXPORT, @EXPORT_OK and %EXPORT_TAGS package variables. + + Exporter::Tiny performs most of its internal duties (including resolution + of tag names to sub names, resolution of sub names to coderefs, and + installation of coderefs into the target package) as method calls, which + means they can be overridden to provide interesting behaviour. + + Utility Functions + These are really for internal use, but can be exported if you need them. + + `mkopt(\@array)` + Similar to `mkopt` from Data::OptList. It doesn't support all the + fancy options that Data::OptList does (`moniker`, `require_unique`, + `must_be` and `name_test`) but runs about 50% faster. + + `mkopt_hash(\@array)` + Similar to `mkopt_hash` from Data::OptList. See also `mkopt`. + +TIPS AND TRICKS IMPORTING FROM EXPORTER::TINY + For the purposes of this discussion we'll assume we have a module called + `MyUtils` which exports one function, `frobnicate`. `MyUtils` inherits + from Exporter::Tiny. + + Many of these tricks may seem familiar from Sub::Exporter. That is + intentional. Exporter::Tiny doesn't attempt to provide every feature of + Sub::Exporter, but where it does it usually uses a fairly similar API. + + Basic importing + # import "frobnicate" function + use MyUtils "frobnicate"; + + # import all functions that MyUtils offers + use MyUtils -all; + + Renaming imported functions + # call it "frob" + use MyUtils "frobnicate" => { -as => "frob" }; + + # call it "my_frobnicate" + use MyUtils "frobnicate" => { -prefix => "my_" }; + + # can set a prefix for *all* functions imported from MyUtils + # by placing the options hashref *first*. + use MyUtils { prefix => "my_" }, "frobnicate"; + # (note the lack of hyphen before `prefix`.) + + # call it "frobnicate_util" + use MyUtils "frobnicate" => { -suffix => "_util" }; + use MyUtils { suffix => "_util" }, "frobnicate"; + + # import it twice with two different names + use MyUtils + "frobnicate" => { -as => "frob" }, + "frobnicate" => { -as => "frbnct" }; + + Lexical subs + { + use Sub::Exporter::Lexical lexical_installer => { -as => "lex" }; + use MyUtils { installer => lex }, "frobnicate"; + + frobnicate(...); # ok + } + + frobnicate(...); # not ok + + Import functions into another package + use MyUtils { into => "OtherPkg" }, "frobnicate"; + + OtherPkg::frobincate(...); + + Import functions into a scalar + my $func; + use MyUtils "frobnicate" => { -as => \$func }; + + $func->(...); + + Import functions into a hash + OK, Sub::Exporter doesn't do this... + + my %funcs; + use MyUtils { into => \%funcs }, "frobnicate"; + + $funcs{frobnicate}->(...); + + DO NOT WANT! + This imports everything except "frobnicate": + + use MyUtils qw( -all !frobnicate ); + + Negated imports always "win", so the following will not import + "frobnicate", no matter how many times you repeat it... + + use MyUtils qw( !frobnicate frobnicate frobnicate frobnicate ); + + Importing by regexp + Here's how you could import all functions beginning with an "f": + + use MyUtils qw( /^F/i ); + + Or import everything except functions beginning with a "z": + + use MyUtils qw( -all !/^Z/i ); + + Note that regexps are always supplied as *strings* starting with "/", and + not as quoted regexp references (`qr/.../`). + + Unimporting + You can unimport the functions that MyUtils added to your namespace: + + no MyUtils; + + Or just specific ones: + + no MyUtils qw(frobnicate); + + If you renamed a function when you imported it, you should unimport by the + new name: + + use MyUtils frobnicate => { -as => "frob" }; + ...; + no MyUtils "frob"; + + Unimporting using tags and regexps should mostly do what you want. + +TIPS AND TRICKS EXPORTING USING EXPORTER::TINY + Simple configuration works the same as Exporter; inherit from this module, + and use the @EXPORT, @EXPORT_OK and %EXPORT_TAGS package variables to list + subs to export. + + Generators + Exporter::Tiny has always allowed exported subs to be generated (like + Sub::Exporter), but until version 0.025 did not have an especially nice + API for it. + + Now, it's easy. If you want to generate a sub `foo` to export, list it in + @EXPORT or @EXPORT_OK as usual, and then simply give your exporter module + a class method called `_generate_foo`. + + push @EXPORT_OK, 'foo'; + + sub _generate_foo { + my $class = shift; + my ($name, $args, $globals) = @_; + + return sub { + ...; + } + } + + You can also generate tags: + + my %constants; + BEGIN { + %constants = (FOO => 1, BAR => 2); + } + use constant \%constants; + + $EXPORT_TAGS{constants} = sub { + my $class = shift; + my ($name, $args, $globals) = @_; + + return keys(%constants); + }; + + Overriding Internals + An important difference between Exporter and Exporter::Tiny is that the + latter calls all its internal functions as *class methods*. This means + that your subclass can *override them* to alter their behaviour. + + The following methods are available to be overridden. Despite being named + with a leading underscore, they are considered public methods. (The + underscore is there to avoid accidentally colliding with any of your own + function names.) + + `_exporter_validate_opts($globals)` + This method is called once each time `import` is called. It is passed + a reference to the global options hash. (That is, the optional leading + hashref in the `use` statement, where the `into` and `installer` + options can be provided.) + + You may use this method to munge the global options, or validate them, + throwing an exception or printing a warning. + + The default implementation does nothing interesting. + + `_exporter_validate_unimport_opts($globals)` + Like `_exporter_validate_opts`, but called for `unimport`. + + `_exporter_merge_opts($tag_opts, $globals, @exports)` + Called to merge options which have been provided for a tag into the + options provided for the exports that the tag expanded to. + + `_exporter_expand_tag($name, $args, $globals)` + This method is called to expand an import tag (e.g. ":constants"). It + is passed the tag name (minus the leading ":"), an optional hashref of + options (like `{ -prefix => "foo_" }`), and the global options + hashref. + + It is expected to return a list of ($name, $args) arrayref pairs. + These names can be sub names to export, or further tag names (which + must have their ":"). If returning tag names, be careful to avoid + creating a tag expansion loop! + + The default implementation uses %EXPORT_TAGS to expand tags, and + provides fallbacks for the `:default` and `:all` tags. + + `_exporter_expand_regexp($regexp, $args, $globals)` + Like `_exporter_expand_regexp`, but given a regexp-like string instead + of a tag name. + + The default implementation greps through @EXPORT_OK for imports, and + the list of already-imported functions for exports. + + `_exporter_expand_sub($name, $args, $globals)` + This method is called to translate a sub name to a hash of name => + coderef pairs for exporting to the caller. In general, this would just + be a hash with one key and one value, but, for example, Type::Library + overrides this method so that "+Foo" gets expanded to: + + ( + Foo => sub { $type }, + is_Foo => sub { $type->check(@_) }, + to_Foo => sub { $type->assert_coerce(@_) }, + assert_Foo => sub { $type->assert_return(@_) }, + ) + + The default implementation checks that the name is allowed to be + exported (using the `_exporter_permitted_regexp` method), gets the + coderef using the generator if there is one (or by calling `can` on + your exporter otherwise) and calls `_exporter_fail` if it's unable to + generate or retrieve a coderef. + + `_exporter_permitted_regexp($globals)` + This method is called to retrieve a regexp for validating the names of + exportable subs. If a sub doesn't match the regexp, then the default + implementation of `_exporter_expand_sub` will refuse to export it. (Of + course, you may override the default `_exporter_expand_sub`.) + + The default implementation of this method assembles the regexp from + @EXPORT and @EXPORT_OK. + + `_exporter_fail($name, $args, $globals)` + Called by `_exporter_expand_sub` if it can't find a coderef to export. + + The default implementation just throws an exception. But you could + emit a warning instead, or just ignore the failed export. + + If you don't throw an exception then you should be aware that this + method is called in list context, and any list it returns will be + treated as an `_exporter_expand_sub`-style hash of names and coderefs + for export. + + `_exporter_install_sub($name, $args, $globals, $coderef)` + This method actually installs the exported sub into its new + destination. Its return value is ignored. + + The default implementation handles sub renaming (i.e. the `-as`, + `-prefix` and `-suffix` functions. This method does a lot of stuff; if + you need to override it, it's probably a good idea to just pre-process + the arguments and then call the super method rather than trying to + handle all of it yourself. + + `_exporter_uninstall_sub($name, $args, $globals)` + The opposite of `_exporter_install_sub`. + +DIAGNOSTICS + Overwriting existing sub '%s::%s' with sub '%s' exported by %s + A warning issued if Exporter::Tiny is asked to export a symbol which + will result in an existing sub being overwritten. This warning can be + suppressed using either of the following: + + use MyUtils { replace => 1 }, "frobnicate"; + use MyUtils "frobnicate" => { -replace => 1 }; + + Or can be upgraded to a fatal error: + + use MyUtils { replace => "die" }, "frobnicate"; + use MyUtils "frobnicate" => { -replace => "die" }; + + Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s + The fatal version of the above warning. + + Could not find sub '%s' exported by %s + You requested to import a sub which the package does not provide. + + Cannot provide an -as option for tags + Because a tag may provide more than one function, it does not make + sense to request a single name for it. Instead use `-prefix` or + `-suffix`. + + Passing options to unimport '%s' makes no sense + When you import a sub, it occasionally makes sense to pass some + options for it. However, when unimporting, options do nothing, so this + warning is issued. + +HISTORY + Type::Library had a bunch of custom exporting code which poked coderefs + into its caller's stash. It needed this to be something more powerful than + most exporters so that it could switch between exporting Moose, Mouse and + Moo-compatible objects on request. Sub::Exporter would have been capable, + but had too many dependencies for the Type::Tiny project. + + Meanwhile Type::Utils, Types::TypeTiny and Test::TypeTiny each used the + venerable Exporter.pm. However, this meant they were unable to use the + features like Sub::Exporter-style function renaming which I'd built into + Type::Library: + + ## import "Str" but rename it to "String". + use Types::Standard "Str" => { -as => "String" }; + + And so I decided to factor out code that could be shared by all + Type-Tiny's exporters into a single place: Exporter::TypeTiny. + + As of version 0.026, Exporter::TypeTiny was also made available as + Exporter::Tiny, distributed independently on CPAN. CHOCOLATEBOY had + convinced me that it was mature enough to live a life of its own. + + As of version 0.030, Type-Tiny depends on Exporter::Tiny and + Exporter::TypeTiny is being phased out. + +OBLIGATORY EXPORTER COMPARISON + Exporting is unlikely to be your application's performance bottleneck, but + nonetheless here are some comparisons. + + Comparative sizes according to Devel::SizeMe: + + Exporter 217.1Kb + Sub::Exporter::Progressive 263.2Kb + Exporter::Tiny 267.7Kb + Exporter + Exporter::Heavy 281.5Kb + Exporter::Renaming 406.2Kb + Sub::Exporter 701.0Kb + + Performance exporting a single sub: + + Rate SubExp ExpTiny SubExpProg ExpPM + SubExp 2489/s -- -56% -85% -88% + ExpTiny 5635/s 126% -- -67% -72% + SubExpProg 16905/s 579% 200% -- -16% + ExpPM 20097/s 707% 257% 19% -- + + (Exporter::Renaming globally changes the behaviour of Exporter.pm, so + could not be included in the same benchmarks.) + + (Non-Core) Dependencies: + + Exporter -1 + Exporter::Renaming 0 + Exporter::Tiny 0 + Sub::Exporter::Progressive 0 + Sub::Exporter 3 + + Features: + + ExpPM ExpTiny SubExp SubExpProg + Can export code symbols............. Yes Yes Yes Yes + Can export non-code symbols......... Yes + Groups/tags......................... Yes Yes Yes Yes + Export by regexp.................... Yes Yes + Bang prefix......................... Yes Yes + Allows renaming of subs............. Yes Yes Maybe + Install code into scalar refs....... Yes Yes Maybe + Can be passed an "into" parameter... Yes Yes Maybe + Can be passed an "installer" sub.... Yes Yes Maybe + Config avoids package variables..... Yes + Supports generators................. Yes Yes + Sane API for generators............. Yes Yes + Unimport............................ Yes + + (Certain Sub::Exporter::Progressive features are only available if + Sub::Exporter is installed.) + +BUGS + Please report any bugs to + <http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny>. + +SUPPORT + IRC: support is available through in the *#moops* channel on irc.perl.org + <http://www.irc.perl.org/channels.html>. + +SEE ALSO + Exporter::Shiny, Sub::Exporter, Exporter. + +AUTHOR + Toby Inkster <tobyink@cpan.org>. + +COPYRIGHT AND LICENCE + This software is copyright (c) 2013-2014 by Toby Inkster. + + This is free software; you can redistribute it and/or modify it under the + same terms as the Perl 5 programming language system itself. + +DISCLAIMER OF WARRANTIES + THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/SIGNATURE b/SIGNATURE new file mode 100644 index 0000000..4d30a89 --- /dev/null +++ b/SIGNATURE @@ -0,0 +1,49 @@ +This file contains message digests of all files listed in MANIFEST, +signed via the Module::Signature module, version 0.73. + +To verify the content in this distribution, first make sure you have +Module::Signature installed, then type: + + % cpansign -v + +It will check each file's integrity, as well as the signature's +validity. If "==> Signature verified OK! <==" is not displayed, +the distribution may already have been compromised, and you should +not run its Makefile.PL or Build.PL. + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +SHA1 33317486c4fa2cf7fec85bf92ed38ac0f64233a0 CONTRIBUTING +SHA1 5980cc638348a4f7438480d881a82ae5e17a1630 COPYRIGHT +SHA1 e3b0c464bb56d4285fa64e31a70b301692dd825c CREDITS +SHA1 5c7b2ac127f2c84b4bac86a882a671fe17a933e3 Changes +SHA1 3b20e9835f489bbf71b1deb6aa7c10729482aa77 INSTALL +SHA1 34f5e12514b91055de4b164a1f2327ef5c30ba53 LICENSE +SHA1 7d98e1b385b7b5d70cb9a1497eea3b233f4baa8a MANIFEST +SHA1 525d4669e3507fc769ab765d6438218af3e9adbb META.json +SHA1 e50e4613cc1d1abd87c290d1f2953eedad430de2 META.yml +SHA1 1c9cf0c5db5b9abf7a137c2db5eebd93baafce48 Makefile.PL +SHA1 29f2538f2e202b70d54cf08d0d7499fa7ddf4c5d README +SHA1 a43593d3e3a79c5f455977ba75083d9f191f6af6 dist.ini +SHA1 066ce57aee9422a1789f0b42a968b3bb16a4c117 doap.ttl +SHA1 3f65666b300ab7e7a1e5e25fb69e4ce6675e0f63 examples/Example/Exporter.pm +SHA1 90df17b2a1b5cf0ddf5e81d7f8c6fcdf6152f800 lib/Exporter/Shiny.pm +SHA1 57ff9abef5131446f439a23224522805307fc743 lib/Exporter/Tiny.pm +SHA1 6ba2757140a1c118ae5bac4c10ea8a6275ee15f2 t/01basic.t +SHA1 8b9c883098fbdaf8999c6f8f909a79297870af86 t/02renaming.t +SHA1 103845d83b41f8d3c503d50e9d6012790b25f77f t/03generators.t +SHA1 6a20cb44b8b22885209f6c3f30cbcf5adb80c52c t/04into.t +SHA1 e50bb7649f42c23b8873dd2e72ef63d85e443b28 t/05shiny.t +SHA1 8c545aab416cd36ee4fde0cc50cf6b59200a9aac t/06notwant.t +SHA1 803a876d8e5e5b5af567f7a3a6e7a1071a4a48ed t/07regexp.t +SHA1 dbce3f55c87fefdfe5abba21afa5a9c9a9a08cf0 t/08tags.t +SHA1 9cc0bdbc9fd24f98161b4d314bc7c841f2fa8efc t/09warnings.t +SHA1 2b5c5da82a5c8f2d69d46915b9921d2ceb6ca214 t/10no.t +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1 + +iEYEARECAAYFAlQwL/wACgkQzr+BKGoqfTkonACeP1ZH9sdg3mJTHQpxoxdgTNQP +I8YAnjYQAQLXP2fg8wYUZKcbDS5aFJml +=JZvp +-----END PGP SIGNATURE----- diff --git a/dist.ini b/dist.ini new file mode 100644 index 0000000..d207ae1 --- /dev/null +++ b/dist.ini @@ -0,0 +1,3 @@ +;;class='Dist::Inkt::Profile::TOBYINK' +;;name='Exporter-Tiny' + diff --git a/doap.ttl b/doap.ttl new file mode 100644 index 0000000..29c03f0 --- /dev/null +++ b/doap.ttl @@ -0,0 +1,348 @@ +@prefix cpan-uri: <http://purl.org/NET/cpan-uri/terms#> . +@prefix dc: <http://purl.org/dc/terms/> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix doap-changeset: <http://ontologi.es/doap-changeset#> . +@prefix doap-deps: <http://ontologi.es/doap-deps#> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . + +<http://dev.perl.org/licenses/> + dc:title "the same terms as the perl 5 programming language system itself". + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/project> + a doap:Project; + cpan-uri:x_IRC <irc://irc.perl.org/#moops>; + dc:contributor <http://purl.org/NET/cpan-uri/person/tobyink>; + doap-deps:runtime-requirement [ doap-deps:on "perl 5.006001"^^doap-deps:CpanId ]; + doap-deps:test-recommendation [ doap-deps:on "Test::Fatal"^^doap-deps:CpanId ], [ doap-deps:on "Test::Warnings"^^doap-deps:CpanId ]; + doap-deps:test-requirement [ doap-deps:on "Test::More 0.47"^^doap-deps:CpanId ]; + doap:bug-database <http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny>; + doap:created "2013-09-05"^^xsd:date; + doap:developer <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:download-page <https://metacpan.org/release/Exporter-Tiny>; + doap:homepage <https://metacpan.org/release/Exporter-Tiny>; + doap:license <http://dev.perl.org/licenses/>; + doap:maintainer <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:name "Exporter-Tiny"; + doap:programming-language "Perl"; + doap:release <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-026>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-029_01>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-030>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-031_01>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-032>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-033_01>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-034>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-035_01>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-035_02>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-036>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_01>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_02>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_03>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-038>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-039_01>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-040>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-041_01>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-041_02>, <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-042>; + doap:repository [ + a doap:GitRepository; + doap:browse <https://github.com/tobyink/p5-exporter-tiny>; + ]; + doap:shortdesc "an exporter with the features of Sub::Exporter but only core dependencies"; + rdfs:seeAlso <http://purl.org/NET/cpan-uri/dist/Type-Tiny/project>. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-026> + a doap:Version; + rdfs:label "Initial release"; + dc:identifier "Exporter-Tiny-0.026"^^xsd:string; + dc:issued "2013-09-05"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Packaging; + rdfs:label "Split Exporter::Tiny out from Exporter::TypeTiny."; + doap-changeset:thanks <http://purl.org/NET/cpan-uri/person/chocolateboy>; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Type-Tiny/v_0-026>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.026.tar.gz>; + doap:revision "0.026"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-029_01> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.029_01"^^xsd:string; + dc:issued "2013-09-26"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Documentation, doap-changeset:Packaging; + rdfs:label "Exporter::TypeTiny is being retired, so modify documentation and distribution metadata for Exporter::Tiny to no longer point there."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-026>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.029_01.tar.gz>; + doap:revision "0.029_01"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-030> + a doap:Version; + dc:identifier "Exporter-Tiny-0.030"^^xsd:string; + dc:issued "2013-09-26"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Tests; + rdfs:label "Test for the 'into' option."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-029_01>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.030.tar.gz>; + doap:revision "0.030"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-031_01> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.031_01"^^xsd:string; + dc:issued "2013-12-30"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Packaging, doap-changeset:Tests; + rdfs:label "No longer require a recent version of Test::More; the Test::More bundled with Perl 5.6.2 should suffice."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-030>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.031_01.tar.gz>; + doap:revision "0.031_01"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-032> + a doap:Version; + dc:identifier "Exporter-Tiny-0.032"^^xsd:string; + dc:issued "2013-12-30"^^xsd:date; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.032.tar.gz>; + doap:revision "0.032"^^xsd:string; + rdfs:comment "No functional changes since 0.031_01.". + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-033_01> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.033_01"^^xsd:string; + dc:issued "2014-01-19"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Addition; + rdfs:label "Add a new wrapper module called Exporter::Shiny."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-032>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.033_01.tar.gz>; + doap:revision "0.033_01"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-034> + a doap:Version; + dc:identifier "Exporter-Tiny-0.034"^^xsd:string; + dc:issued "2014-01-19"^^xsd:date; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.034.tar.gz>; + doap:revision "0.034"^^xsd:string; + rdfs:comment "No functional changes since 0.033_01.". + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-035_01> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.035_01"^^xsd:string; + dc:issued "2014-03-01"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Packaging; + rdfs:label "Explicitly list minimum Perl version: 5.6.1."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-034>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.035_01.tar.gz>; + doap:revision "0.035_01"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-035_02> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.035_02"^^xsd:string; + dc:issued "2014-03-01"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Documentation; + rdfs:label "Document exactly what Exporter::Shiny is supposed to do."; + ], [ + a doap-changeset:Tests; + rdfs:label "Make t/02renaming.t less noisy."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-035_01>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.035_02.tar.gz>; + doap:revision "0.035_02"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-036> + a doap:Version; + dc:identifier "Exporter-Tiny-0.036"^^xsd:string; + dc:issued "2014-03-11"^^xsd:date; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.036.tar.gz>; + doap:revision "0.036"^^xsd:string; + rdfs:comment "No functional changes since 0.035_02.". + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_01> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.037_01"^^xsd:string; + dc:issued "2014-03-26"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Documentation; + rdfs:label "Fix minor error in documentation of generators."; + ], [ + a doap-changeset:Addition; + rdfs:label "Support Exporter.pm's import negation syntax qw( !foo )."; + ], [ + a doap-changeset:Addition; + rdfs:label "Support Exporter.pm's regexp import syntax qw( /foo/ )."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-036>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.037_01.tar.gz>; + doap:revision "0.037_01"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_02> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.037_02"^^xsd:string; + dc:issued "2014-04-02"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Change; + rdfs:label "Improved handling of hashrefs of options passed to tags, and hashrefs of options found within %EXPORT_TAGS arrayrefs."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_01>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.037_02.tar.gz>; + doap:revision "0.037_02"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_03> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.037_03"^^xsd:string; + dc:issued "2014-04-02"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Bugfix; + rdfs:label "Only attempt to merge hashes if we're sure they're both really hashes!"; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-037_02>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.037_03.tar.gz>; + doap:revision "0.037_03"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-038> + a doap:Version; + dc:identifier "Exporter-Tiny-0.038"^^xsd:string; + dc:issued "2014-04-04"^^xsd:date; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.038.tar.gz>; + doap:revision "0.038"^^xsd:string; + rdfs:comment "No functional changes since 0.037_03.". + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-039_01> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.039_01"^^xsd:string; + dc:issued "2014-07-20"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Documentation; + rdfs:label "Document warning and error messages produced by Exporter::Tiny."; + ], [ + a doap-changeset:Change; + rdfs:label "No longer die when redefining locally defined subs."; + ], [ + a doap-changeset:Change; + rdfs:label "Warn when redefining any subs."; + ], [ + a doap-changeset:Change; + rdfs:label "Exporter::Tiny would previously cause B.pm to be loaded into memory any time it exported anything. It no longer does."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-038>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.039_01.tar.gz>; + doap:revision "0.039_01"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-040> + a doap:Version; + dc:identifier "Exporter-Tiny-0.040"^^xsd:string; + dc:issued "2014-09-17"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Packaging; + rdfs:label "Repackage as a stable release."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-039_01>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.040.tar.gz>; + doap:revision "0.040"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-041_01> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.041_01"^^xsd:string; + dc:issued "2014-09-18"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Change; + rdfs:label "Add an `unimport` feature."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-040>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.041_01.tar.gz>; + doap:revision "0.041_01"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-041_02> + a cpan-uri:DeveloperRelease, doap:Version; + dc:identifier "Exporter-Tiny-0.041_02"^^xsd:string; + dc:issued "2014-09-19"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Bugfix; + rdfs:label "Option validation needs to happen after expanding tags."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-041_01>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.041_02.tar.gz>; + doap:revision "0.041_02"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-042> + a doap:Version; + dc:identifier "Exporter-Tiny-0.042"^^xsd:string; + dc:issued "2014-10-04"^^xsd:date; + doap-changeset:changeset [ + doap-changeset:item [ + a doap-changeset:Documentation; + rdfs:label "Document the warning emitted when you provide options to a function you are unimporting."; + ], [ + a doap-changeset:Change; + rdfs:label "Housekeeping on %TRACKED."; + ]; + doap-changeset:versus <http://purl.org/NET/cpan-uri/dist/Exporter-Tiny/v_0-041_02>; + ]; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Exporter-Tiny-0.042.tar.gz>; + doap:revision "0.042"^^xsd:string. + +<http://purl.org/NET/cpan-uri/dist/Type-Tiny/project> + a doap:Project; + dc:contributor <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:download-page <https://metacpan.org/release/Type-Tiny>; + doap:homepage <https://metacpan.org/release/Type-Tiny>; + doap:name "Type-Tiny"; + doap:programming-language "Perl"; + doap:release <http://purl.org/NET/cpan-uri/dist/Type-Tiny/v_0-026>. + +<http://purl.org/NET/cpan-uri/dist/Type-Tiny/v_0-026> + a doap:Version; + dc:identifier "Type-Tiny-0.026"^^xsd:string; + doap-changeset:released-by <http://purl.org/NET/cpan-uri/person/tobyink>; + doap:file-release <http://backpan.cpan.org/authors/id/T/TO/TOBYINK/Type-Tiny-0.026.tar.gz>; + doap:revision "0.026"^^xsd:string. + +<http://purl.org/NET/cpan-uri/person/chocolateboy> + a foaf:Person; + foaf:nick "CHOCOLATEBOY"; + foaf:page <https://metacpan.org/author/CHOCOLATEBOY>. + +<http://purl.org/NET/cpan-uri/person/tobyink> + a foaf:Person; + foaf:mbox <mailto:tobyink@cpan.org>; + foaf:name "Toby Inkster"; + foaf:nick "TOBYINK"; + foaf:page <https://metacpan.org/author/TOBYINK>. + diff --git a/examples/Example/Exporter.pm b/examples/Example/Exporter.pm new file mode 100644 index 0000000..dedc876 --- /dev/null +++ b/examples/Example/Exporter.pm @@ -0,0 +1,56 @@ +use 5.006001; +use strict; +use warnings; + +package Example::Exporter; + +# Inherit from Exporter::Tiny. +# +use base 'Exporter::Tiny'; + +# The list of functions to export by default. +# Be conservative. +# +our @EXPORT = qw( fib ); + +# The list of functions which are allowed to +# be exported. Be liberal. +# +our @EXPORT_OK = qw( embiggen ); + +# Note that there was no need to list "fib" +# in @EXPORT_OK. It was in @EXPORT, so it's +# implicitly ok. + +# This is the definition of the "fib" function +# that we want to export. +# +sub fib { + my $n = $_[0]; + + (int($n) eq $n) && ($n >= 0) + or die "Expected natural number as argument; got '$n'"; + + return $n if $n < 2; + + fib($n - 1) + fib($n - 2); +} + +# We won't define a standard embiggen function. +# Instead we will generate one when requested. +# +sub _generate_embiggen { + my ($class, $name, $arg, $globals) = @_; + + my $embiggen_amount = exists($arg->{amount}) ? $arg->{amount} : 1; + + # This is the sub that will be installed into + # the caller's namespace. + # + return sub ($) { + my $n = $_[0]; + return $n + $embiggen_amount; + } +} + +1; # Make Perl Happyâ„¢ diff --git a/lib/Exporter/Shiny.pm b/lib/Exporter/Shiny.pm new file mode 100644 index 0000000..063cb47 --- /dev/null +++ b/lib/Exporter/Shiny.pm @@ -0,0 +1,111 @@ +package Exporter::Shiny; + +use 5.006001; +use strict; +use warnings; + +use Exporter::Tiny (); + +our $AUTHORITY = 'cpan:TOBYINK'; +our $VERSION = '0.042'; + +sub import { + my $me = shift; + my $caller = caller; + + (my $nominal_file = $caller) =~ s(::)(/)g; + $INC{"$nominal_file\.pm"} ||= __FILE__; + + if (@_ == 2 and $_[0] eq -setup) + { + my (undef, $opts) = @_; + @_ = @{ delete($opts->{exports}) || [] }; + + if (%$opts) { + Exporter::Tiny::_croak( + 'Unsupported Sub::Exporter-style options: %s', + join(q[, ], sort keys %$opts), + ); + } + } + + ref($_) && Exporter::Tiny::_croak('Expected sub name, got ref %s', $_) for @_; + + no strict qw(refs); + push @{"$caller\::ISA"}, 'Exporter::Tiny'; + push @{"$caller\::EXPORT_OK"}, @_; +} + +1; + +__END__ + +=pod + +=encoding utf-8 + +=head1 NAME + +Exporter::Shiny - shortcut for Exporter::Tiny + +=head1 SYNOPSIS + + use Exporter::Shiny qw( foo bar ); + +Is a shortcut for: + + use base "Exporter::Tiny"; + push our(@EXPORT_OK), qw( foo bar ); + +For compatibility with L<Sub::Exporter>, the following longer syntax is +also supported: + + use Exporter::Shiny -setup => { + exports => [qw( foo bar )], + }; + +=head1 DESCRIPTION + +This is a very small wrapper to simplify using L<Exporter::Tiny>. + +It does the following: + +=over + +=item * Marks your package as loaded in C<< %INC >>; + +=item * Pushes any function names in the import list onto your C<< @EXPORT_OK >>; and + +=item * Pushes C<< "Exporter::Tiny" >> onto your C<< @ISA >>. + +=back + +It doesn't set up C<< %EXPORT_TAGS >> or C<< @EXPORT >>, but there's +nothing stopping you doing that yourself. + +=head1 BUGS + +Please report any bugs to +L<http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny>. + +=head1 SEE ALSO + +L<Exporter::Tiny>. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=head1 DISCLAIMER OF WARRANTIES + +THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/lib/Exporter/Tiny.pm b/lib/Exporter/Tiny.pm new file mode 100644 index 0000000..6e77338 --- /dev/null +++ b/lib/Exporter/Tiny.pm @@ -0,0 +1,833 @@ +package Exporter::Tiny; + +use 5.006001; +use strict; +use warnings; no warnings qw(void once uninitialized numeric redefine); + +our $AUTHORITY = 'cpan:TOBYINK'; +our $VERSION = '0.042'; +our @EXPORT_OK = qw< mkopt mkopt_hash _croak _carp >; + +sub _croak ($;@) { require Carp; my $fmt = shift; @_ = sprintf($fmt, @_); goto \&Carp::croak } +sub _carp ($;@) { require Carp; my $fmt = shift; @_ = sprintf($fmt, @_); goto \&Carp::carp } + +my $_process_optlist = sub +{ + my $class = shift; + my ($global_opts, $opts, $want, $not_want) = @_; + + while (@$opts) + { + my $opt = shift @{$opts}; + my ($name, $value) = @$opt; + + ($name =~ m{\A\!(/.+/[msixpodual]+)\z}) ? + do { + my @not = $class->_exporter_expand_regexp($1, $value, $global_opts); + ++$not_want->{$_->[0]} for @not; + } : + ($name =~ m{\A\!(.+)\z}) ? + (++$not_want->{$1}) : + ($name =~ m{\A[:-](.+)\z}) ? + push(@$opts, $class->_exporter_expand_tag($1, $value, $global_opts)) : + ($name =~ m{\A/.+/[msixpodual]+\z}) ? + push(@$opts, $class->_exporter_expand_regexp($name, $value, $global_opts)) : + # else ? + push(@$want, $opt); + } +}; + +sub import +{ + my $class = shift; + my $global_opts = +{ @_ && ref($_[0]) eq q(HASH) ? %{+shift} : () }; + $global_opts->{into} = caller unless exists $global_opts->{into}; + + my @want; + my %not_want; $global_opts->{not} = \%not_want; + my @args = do { no strict qw(refs); @_ ? @_ : @{"$class\::EXPORT"} }; + my $opts = mkopt(\@args); + $class->$_process_optlist($global_opts, $opts, \@want, \%not_want); + + my $permitted = $class->_exporter_permitted_regexp($global_opts); + $class->_exporter_validate_opts($global_opts); + + for my $wanted (@want) + { + next if $not_want{$wanted->[0]}; + + my %symbols = $class->_exporter_expand_sub(@$wanted, $global_opts, $permitted); + $class->_exporter_install_sub($_, $wanted->[1], $global_opts, $symbols{$_}) + for keys %symbols; + } +} + +sub unimport +{ + my $class = shift; + my $global_opts = +{ @_ && ref($_[0]) eq q(HASH) ? %{+shift} : () }; + $global_opts->{into} = caller unless exists $global_opts->{into}; + $global_opts->{is_unimport} = 1; + + my @want; + my %not_want; $global_opts->{not} = \%not_want; + my @args = do { our %TRACKED; @_ ? @_ : keys(%{$TRACKED{$class}{$global_opts->{into}}}) }; + my $opts = mkopt(\@args); + $class->$_process_optlist($global_opts, $opts, \@want, \%not_want); + + my $permitted = $class->_exporter_permitted_regexp($global_opts); + $class->_exporter_validate_unimport_opts($global_opts); + + my $expando = $class->can('_exporter_expand_sub'); + $expando = undef if $expando == \&_exporter_expand_sub; + + for my $wanted (@want) + { + next if $not_want{$wanted->[0]}; + + if ($wanted->[1]) + { + _carp("Passing options to unimport '%s' makes no sense", $wanted->[0]) + unless (ref($wanted->[1]) eq 'HASH' and not keys %{$wanted->[1]}); + } + + my %symbols = defined($expando) + ? $class->$expando(@$wanted, $global_opts, $permitted) + : ($wanted->[0] => sub { "dummy" }); + $class->_exporter_uninstall_sub($_, $wanted->[1], $global_opts) + for keys %symbols; + } +} + +# Called once per import/unimport, passed the "global" import options. +# Expected to validate the options and carp or croak if there are problems. +# Can also take the opportunity to do other stuff if needed. +# +sub _exporter_validate_opts { 1 } +sub _exporter_validate_unimport_opts { 1 } + +# Called after expanding a tag or regexp to merge the tag's options with +# any sub-specific options. +# +sub _exporter_merge_opts +{ + my $class = shift; + my ($tag_opts, $global_opts, @stuff) = @_; + + $tag_opts = {} unless ref($tag_opts) eq q(HASH); + _croak('Cannot provide an -as option for tags') + if exists $tag_opts->{-as}; + + my $optlist = mkopt(\@stuff); + for my $export (@$optlist) + { + next if defined($export->[1]) && ref($export->[1]) ne q(HASH); + + my %sub_opts = ( %{ $export->[1] or {} }, %$tag_opts ); + $sub_opts{-prefix} = sprintf('%s%s', $tag_opts->{-prefix}, $export->[1]{-prefix}) + if exists($export->[1]{-prefix}) && exists($tag_opts->{-prefix}); + $sub_opts{-suffix} = sprintf('%s%s', $export->[1]{-suffix}, $tag_opts->{-suffix}) + if exists($export->[1]{-suffix}) && exists($tag_opts->{-suffix}); + $export->[1] = \%sub_opts; + } + return @$optlist; +} + +# Given a tag name, looks it up in %EXPORT_TAGS and returns the list of +# associated functions. The default implementation magically handles tags +# "all" and "default". The default implementation interprets any undefined +# tags as being global options. +# +sub _exporter_expand_tag +{ + no strict qw(refs); + + my $class = shift; + my ($name, $value, $globals) = @_; + my $tags = \%{"$class\::EXPORT_TAGS"}; + + return $class->_exporter_merge_opts($value, $globals, $tags->{$name}->($class, @_)) + if ref($tags->{$name}) eq q(CODE); + + return $class->_exporter_merge_opts($value, $globals, @{$tags->{$name}}) + if exists $tags->{$name}; + + return $class->_exporter_merge_opts($value, $globals, @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"}) + if $name eq 'all'; + + return $class->_exporter_merge_opts($value, $globals, @{"$class\::EXPORT"}) + if $name eq 'default'; + + $globals->{$name} = $value || 1; + return; +} + +# Given a regexp-like string, looks it up in @EXPORT_OK and returns the +# list of matching functions. +# +sub _exporter_expand_regexp +{ + no strict qw(refs); + our %TRACKED; + + my $class = shift; + my ($name, $value, $globals) = @_; + my $compiled = eval("qr$name"); + + my @possible = $globals->{is_unimport} + ? keys( %{$TRACKED{$class}{$globals->{into}}} ) + : @{"$class\::EXPORT_OK"}; + + $class->_exporter_merge_opts($value, $globals, grep /$compiled/, @possible); +} + +# Helper for _exporter_expand_sub. Returns a regexp matching all subs in +# the exporter package which are available for export. +# +sub _exporter_permitted_regexp +{ + no strict qw(refs); + my $class = shift; + my $re = join "|", map quotemeta, sort { + length($b) <=> length($a) or $a cmp $b + } @{"$class\::EXPORT"}, @{"$class\::EXPORT_OK"}; + qr{^(?:$re)$}ms; +} + +# Given a sub name, returns a hash of subs to install (usually just one sub). +# Keys are sub names, values are coderefs. +# +sub _exporter_expand_sub +{ + my $class = shift; + my ($name, $value, $globals, $permitted) = @_; + $permitted ||= $class->_exporter_permitted_regexp($globals); + + no strict qw(refs); + + if ($name =~ $permitted) + { + my $generator = $class->can("_generate_$name"); + return $name => $class->$generator($name, $value, $globals) if $generator; + + my $sub = $class->can($name); + return $name => $sub if $sub; + } + + $class->_exporter_fail(@_); +} + +# Called by _exporter_expand_sub if it is unable to generate a key-value +# pair for a sub. +# +sub _exporter_fail +{ + my $class = shift; + my ($name, $value, $globals) = @_; + return if $globals->{is_unimport}; + _croak("Could not find sub '%s' exported by %s", $name, $class); +} + +# Actually performs the installation of the sub into the target package. This +# also handles renaming the sub. +# +sub _exporter_install_sub +{ + my $class = shift; + my ($name, $value, $globals, $sym) = @_; + + my $into = $globals->{into}; + my $installer = $globals->{installer} || $globals->{exporter}; + + $name = $value->{-as} || $name; + unless (ref($name) eq q(SCALAR)) + { + my ($prefix) = grep defined, $value->{-prefix}, $globals->{prefix}, q(); + my ($suffix) = grep defined, $value->{-suffix}, $globals->{suffix}, q(); + $name = "$prefix$name$suffix"; + } + + return ($$name = $sym) if ref($name) eq q(SCALAR); + return ($into->{$name} = $sym) if ref($into) eq q(HASH); + + no strict qw(refs); + + if (exists &{"$into\::$name"} and \&{"$into\::$name"} != $sym) + { + my ($level) = grep defined, $value->{-replace}, $globals->{replace}, q(0); + my $action = { + carp => \&_carp, + 0 => \&_carp, + '' => \&_carp, + warn => \&_carp, + nonfatal => \&_carp, + croak => \&_croak, + fatal => \&_croak, + die => \&_croak, + }->{$level} || sub {}; + + $action->( + $action == \&_croak + ? "Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s" + : "Overwriting existing sub '%s::%s' with sub '%s' exported by %s", + $into, + $name, + $_[0], + $class, + ); + } + + our %TRACKED; + $TRACKED{$class}{$into}{$name} = $sym; + + no warnings qw(prototype); + $installer + ? $installer->($globals, [$name, $sym]) + : (*{"$into\::$name"} = $sym); +} + +sub _exporter_uninstall_sub +{ + our %TRACKED; + my $class = shift; + my ($name, $value, $globals, $sym) = @_; + my $into = $globals->{into}; + ref $into and return; + + no strict qw(refs); + + # Cowardly refuse to uninstall a sub that differs from the one + # we installed! + my $our_coderef = $TRACKED{$class}{$into}{$name}; + my $cur_coderef = exists(&{"$into\::$name"}) ? \&{"$into\::$name"} : -1; + return unless $our_coderef == $cur_coderef; + + my $stash = \%{"$into\::"}; + my $old = delete $stash->{$name}; + my $full_name = join('::', $into, $name); + foreach my $type (qw(SCALAR HASH ARRAY IO)) # everything but the CODE + { + next unless defined(*{$old}{$type}); + *$full_name = *{$old}{$type}; + } + + delete $TRACKED{$class}{$into}{$name}; +} + +sub mkopt +{ + my $in = shift or return []; + my @out; + + $in = [map(($_ => ref($in->{$_}) ? $in->{$_} : ()), sort keys %$in)] + if ref($in) eq q(HASH); + + for (my $i = 0; $i < @$in; $i++) + { + my $k = $in->[$i]; + my $v; + + ($i == $#$in) ? ($v = undef) : + !defined($in->[$i+1]) ? (++$i, ($v = undef)) : + !ref($in->[$i+1]) ? ($v = undef) : + ($v = $in->[++$i]); + + push @out, [ $k => $v ]; + } + + \@out; +} + +sub mkopt_hash +{ + my $in = shift or return; + my %out = map +($_->[0] => $_->[1]), @{ mkopt($in) }; + \%out; +} + +1; + +__END__ + +=pod + +=encoding utf-8 + +=for stopwords frobnicate greps regexps + +=head1 NAME + +Exporter::Tiny - an exporter with the features of Sub::Exporter but only core dependencies + +=head1 SYNOPSIS + + package MyUtils; + use base "Exporter::Tiny"; + our @EXPORT = qw(frobnicate); + sub frobnicate { my $n = shift; ... } + 1; + + package MyScript; + use MyUtils "frobnicate" => { -as => "frob" }; + print frob(42); + exit; + +=head1 DESCRIPTION + +Exporter::Tiny supports many of Sub::Exporter's external-facing features +including renaming imported functions with the C<< -as >>, C<< -prefix >> and +C<< -suffix >> options; explicit destinations with the C<< into >> option; +and alternative installers with the C<< installler >> option. But it's written +in only about 40% as many lines of code and with zero non-core dependencies. + +Its internal-facing interface is closer to Exporter.pm, with configuration +done through the C<< @EXPORT >>, C<< @EXPORT_OK >> and C<< %EXPORT_TAGS >> +package variables. + +Exporter::Tiny performs most of its internal duties (including resolution +of tag names to sub names, resolution of sub names to coderefs, and +installation of coderefs into the target package) as method calls, which +means they can be overridden to provide interesting behaviour. + +=head2 Utility Functions + +These are really for internal use, but can be exported if you need them. + +=over + +=item C<< mkopt(\@array) >> + +Similar to C<mkopt> from L<Data::OptList>. It doesn't support all the +fancy options that Data::OptList does (C<moniker>, C<require_unique>, +C<must_be> and C<name_test>) but runs about 50% faster. + +=item C<< mkopt_hash(\@array) >> + +Similar to C<mkopt_hash> from L<Data::OptList>. See also C<mkopt>. + +=back + +=head1 TIPS AND TRICKS IMPORTING FROM EXPORTER::TINY + +For the purposes of this discussion we'll assume we have a module called +C<< MyUtils >> which exports one function, C<< frobnicate >>. C<< MyUtils >> +inherits from Exporter::Tiny. + +Many of these tricks may seem familiar from L<Sub::Exporter>. That is +intentional. Exporter::Tiny doesn't attempt to provide every feature of +Sub::Exporter, but where it does it usually uses a fairly similar API. + +=head2 Basic importing + + # import "frobnicate" function + use MyUtils "frobnicate"; + + # import all functions that MyUtils offers + use MyUtils -all; + +=head2 Renaming imported functions + + # call it "frob" + use MyUtils "frobnicate" => { -as => "frob" }; + + # call it "my_frobnicate" + use MyUtils "frobnicate" => { -prefix => "my_" }; + + # can set a prefix for *all* functions imported from MyUtils + # by placing the options hashref *first*. + use MyUtils { prefix => "my_" }, "frobnicate"; + # (note the lack of hyphen before `prefix`.) + + # call it "frobnicate_util" + use MyUtils "frobnicate" => { -suffix => "_util" }; + use MyUtils { suffix => "_util" }, "frobnicate"; + + # import it twice with two different names + use MyUtils + "frobnicate" => { -as => "frob" }, + "frobnicate" => { -as => "frbnct" }; + +=head2 Lexical subs + + { + use Sub::Exporter::Lexical lexical_installer => { -as => "lex" }; + use MyUtils { installer => lex }, "frobnicate"; + + frobnicate(...); # ok + } + + frobnicate(...); # not ok + +=head2 Import functions into another package + + use MyUtils { into => "OtherPkg" }, "frobnicate"; + + OtherPkg::frobincate(...); + +=head2 Import functions into a scalar + + my $func; + use MyUtils "frobnicate" => { -as => \$func }; + + $func->(...); + +=head2 Import functions into a hash + +OK, Sub::Exporter doesn't do this... + + my %funcs; + use MyUtils { into => \%funcs }, "frobnicate"; + + $funcs{frobnicate}->(...); + +=head2 DO NOT WANT! + +This imports everything except "frobnicate": + + use MyUtils qw( -all !frobnicate ); + +Negated imports always "win", so the following will not import +"frobnicate", no matter how many times you repeat it... + + use MyUtils qw( !frobnicate frobnicate frobnicate frobnicate ); + +=head2 Importing by regexp + +Here's how you could import all functions beginning with an "f": + + use MyUtils qw( /^F/i ); + +Or import everything except functions beginning with a "z": + + use MyUtils qw( -all !/^Z/i ); + +Note that regexps are always supplied as I<strings> starting with +C<< "/" >>, and not as quoted regexp references (C<< qr/.../ >>). + +=head2 Unimporting + +You can unimport the functions that MyUtils added to your namespace: + + no MyUtils; + +Or just specific ones: + + no MyUtils qw(frobnicate); + +If you renamed a function when you imported it, you should unimport by +the new name: + + use MyUtils frobnicate => { -as => "frob" }; + ...; + no MyUtils "frob"; + +Unimporting using tags and regexps should mostly do what you want. + +=head1 TIPS AND TRICKS EXPORTING USING EXPORTER::TINY + +Simple configuration works the same as L<Exporter>; inherit from this module, +and use the C<< @EXPORT >>, C<< @EXPORT_OK >> and C<< %EXPORT_TAGS >> +package variables to list subs to export. + +=head2 Generators + +Exporter::Tiny has always allowed exported subs to be generated (like +L<Sub::Exporter>), but until version 0.025 did not have an especially nice +API for it. + +Now, it's easy. If you want to generate a sub C<foo> to export, list it in +C<< @EXPORT >> or C<< @EXPORT_OK >> as usual, and then simply give your +exporter module a class method called C<< _generate_foo >>. + + push @EXPORT_OK, 'foo'; + + sub _generate_foo { + my $class = shift; + my ($name, $args, $globals) = @_; + + return sub { + ...; + } + } + +You can also generate tags: + + my %constants; + BEGIN { + %constants = (FOO => 1, BAR => 2); + } + use constant \%constants; + + $EXPORT_TAGS{constants} = sub { + my $class = shift; + my ($name, $args, $globals) = @_; + + return keys(%constants); + }; + +=head2 Overriding Internals + +An important difference between L<Exporter> and Exporter::Tiny is that +the latter calls all its internal functions as I<< class methods >>. This +means that your subclass can I<< override them >> to alter their behaviour. + +The following methods are available to be overridden. Despite being named +with a leading underscore, they are considered public methods. (The underscore +is there to avoid accidentally colliding with any of your own function names.) + +=over + +=item C<< _exporter_validate_opts($globals) >> + +This method is called once each time C<import> is called. It is passed a +reference to the global options hash. (That is, the optional leading hashref +in the C<use> statement, where the C<into> and C<installer> options can be +provided.) + +You may use this method to munge the global options, or validate them, +throwing an exception or printing a warning. + +The default implementation does nothing interesting. + +=item C<< _exporter_validate_unimport_opts($globals) >> + +Like C<_exporter_validate_opts>, but called for C<unimport>. + +=item C<< _exporter_merge_opts($tag_opts, $globals, @exports) >> + +Called to merge options which have been provided for a tag into the +options provided for the exports that the tag expanded to. + +=item C<< _exporter_expand_tag($name, $args, $globals) >> + +This method is called to expand an import tag (e.g. C<< ":constants" >>). +It is passed the tag name (minus the leading ":"), an optional hashref +of options (like C<< { -prefix => "foo_" } >>), and the global options +hashref. + +It is expected to return a list of ($name, $args) arrayref pairs. These +names can be sub names to export, or further tag names (which must have +their ":"). If returning tag names, be careful to avoid creating a tag +expansion loop! + +The default implementation uses C<< %EXPORT_TAGS >> to expand tags, and +provides fallbacks for the C<< :default >> and C<< :all >> tags. + +=item C<< _exporter_expand_regexp($regexp, $args, $globals) >> + +Like C<_exporter_expand_regexp>, but given a regexp-like string instead +of a tag name. + +The default implementation greps through C<< @EXPORT_OK >> for imports, +and the list of already-imported functions for exports. + +=item C<< _exporter_expand_sub($name, $args, $globals) >> + +This method is called to translate a sub name to a hash of name => coderef +pairs for exporting to the caller. In general, this would just be a hash with +one key and one value, but, for example, L<Type::Library> overrides this +method so that C<< "+Foo" >> gets expanded to: + + ( + Foo => sub { $type }, + is_Foo => sub { $type->check(@_) }, + to_Foo => sub { $type->assert_coerce(@_) }, + assert_Foo => sub { $type->assert_return(@_) }, + ) + +The default implementation checks that the name is allowed to be exported +(using the C<_exporter_permitted_regexp> method), gets the coderef using +the generator if there is one (or by calling C<< can >> on your exporter +otherwise) and calls C<_exporter_fail> if it's unable to generate or +retrieve a coderef. + +=item C<< _exporter_permitted_regexp($globals) >> + +This method is called to retrieve a regexp for validating the names of +exportable subs. If a sub doesn't match the regexp, then the default +implementation of C<_exporter_expand_sub> will refuse to export it. (Of +course, you may override the default C<_exporter_expand_sub>.) + +The default implementation of this method assembles the regexp from +C<< @EXPORT >> and C<< @EXPORT_OK >>. + +=item C<< _exporter_fail($name, $args, $globals) >> + +Called by C<_exporter_expand_sub> if it can't find a coderef to export. + +The default implementation just throws an exception. But you could emit +a warning instead, or just ignore the failed export. + +If you don't throw an exception then you should be aware that this +method is called in list context, and any list it returns will be treated +as an C<_exporter_expand_sub>-style hash of names and coderefs for +export. + +=item C<< _exporter_install_sub($name, $args, $globals, $coderef) >> + +This method actually installs the exported sub into its new destination. +Its return value is ignored. + +The default implementation handles sub renaming (i.e. the C<< -as >>, +C<< -prefix >> and C<< -suffix >> functions. This method does a lot of +stuff; if you need to override it, it's probably a good idea to just +pre-process the arguments and then call the super method rather than +trying to handle all of it yourself. + +=item C<< _exporter_uninstall_sub($name, $args, $globals) >> + +The opposite of C<_exporter_install_sub>. + +=back + +=head1 DIAGNOSTICS + +=over + +=item B<< Overwriting existing sub '%s::%s' with sub '%s' exported by %s >> + +A warning issued if Exporter::Tiny is asked to export a symbol which +will result in an existing sub being overwritten. This warning can be +suppressed using either of the following: + + use MyUtils { replace => 1 }, "frobnicate"; + use MyUtils "frobnicate" => { -replace => 1 }; + +Or can be upgraded to a fatal error: + + use MyUtils { replace => "die" }, "frobnicate"; + use MyUtils "frobnicate" => { -replace => "die" }; + +=item B<< Refusing to overwrite existing sub '%s::%s' with sub '%s' exported by %s >> + +The fatal version of the above warning. + +=item B<< Could not find sub '%s' exported by %s >> + +You requested to import a sub which the package does not provide. + +=item B<< Cannot provide an -as option for tags >> + +Because a tag may provide more than one function, it does not make sense +to request a single name for it. Instead use C<< -prefix >> or C<< -suffix >>. + +=item B<< Passing options to unimport '%s' makes no sense >> + +When you import a sub, it occasionally makes sense to pass some options +for it. However, when unimporting, options do nothing, so this warning +is issued. + +=back + +=head1 HISTORY + +L<Type::Library> had a bunch of custom exporting code which poked coderefs +into its caller's stash. It needed this to be something more powerful than +most exporters so that it could switch between exporting Moose, Mouse and +Moo-compatible objects on request. L<Sub::Exporter> would have been capable, +but had too many dependencies for the Type::Tiny project. + +Meanwhile L<Type::Utils>, L<Types::TypeTiny> and L<Test::TypeTiny> each +used the venerable L<Exporter.pm|Exporter>. However, this meant they were +unable to use the features like L<Sub::Exporter>-style function renaming +which I'd built into Type::Library: + + ## import "Str" but rename it to "String". + use Types::Standard "Str" => { -as => "String" }; + +And so I decided to factor out code that could be shared by all Type-Tiny's +exporters into a single place: Exporter::TypeTiny. + +As of version 0.026, Exporter::TypeTiny was also made available as +L<Exporter::Tiny>, distributed independently on CPAN. CHOCOLATEBOY had +convinced me that it was mature enough to live a life of its own. + +As of version 0.030, Type-Tiny depends on Exporter::Tiny and +Exporter::TypeTiny is being phased out. + +=head1 OBLIGATORY EXPORTER COMPARISON + +Exporting is unlikely to be your application's performance bottleneck, but +nonetheless here are some comparisons. + +B<< Comparative sizes according to L<Devel::SizeMe>: >> + + Exporter 217.1Kb + Sub::Exporter::Progressive 263.2Kb + Exporter::Tiny 267.7Kb + Exporter + Exporter::Heavy 281.5Kb + Exporter::Renaming 406.2Kb + Sub::Exporter 701.0Kb + +B<< Performance exporting a single sub: >> + + Rate SubExp ExpTiny SubExpProg ExpPM +SubExp 2489/s -- -56% -85% -88% +ExpTiny 5635/s 126% -- -67% -72% +SubExpProg 16905/s 579% 200% -- -16% +ExpPM 20097/s 707% 257% 19% -- + +(Exporter::Renaming globally changes the behaviour of Exporter.pm, so could +not be included in the same benchmarks.) + +B<< (Non-Core) Dependencies: >> + + Exporter -1 + Exporter::Renaming 0 + Exporter::Tiny 0 + Sub::Exporter::Progressive 0 + Sub::Exporter 3 + +B<< Features: >> + + ExpPM ExpTiny SubExp SubExpProg + Can export code symbols............. Yes Yes Yes Yes + Can export non-code symbols......... Yes + Groups/tags......................... Yes Yes Yes Yes + Export by regexp.................... Yes Yes + Bang prefix......................... Yes Yes + Allows renaming of subs............. Yes Yes Maybe + Install code into scalar refs....... Yes Yes Maybe + Can be passed an "into" parameter... Yes Yes Maybe + Can be passed an "installer" sub.... Yes Yes Maybe + Config avoids package variables..... Yes + Supports generators................. Yes Yes + Sane API for generators............. Yes Yes + Unimport............................ Yes + +(Certain Sub::Exporter::Progressive features are only available if +Sub::Exporter is installed.) + +=head1 BUGS + +Please report any bugs to +L<http://rt.cpan.org/Dist/Display.html?Queue=Exporter-Tiny>. + +=head1 SUPPORT + +B<< IRC: >> support is available through in the I<< #moops >> channel +on L<irc.perl.org|http://www.irc.perl.org/channels.html>. + +=head1 SEE ALSO + +L<Exporter::Shiny>, +L<Sub::Exporter>, +L<Exporter>. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013-2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=head1 DISCLAIMER OF WARRANTIES + +THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + diff --git a/t/01basic.t b/t/01basic.t new file mode 100644 index 0000000..72dd3d7 --- /dev/null +++ b/t/01basic.t @@ -0,0 +1,38 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Very basic Exporter::Tiny test. + +Check that it allows us to import the functions named in C<< @EXPORT >>. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + + +=cut + +use strict; +use warnings; +use Test::More tests => 2; + +use lib qw( examples ../examples ); + +use Example::Exporter; + +diag("Perl $]"); + +is fib(6), 8, 'Correctly imported "fib" from Example::Exporter'; + +ok !__PACKAGE__->can('embiggen'), 'Did not inadvertantly import "embiggen"'; + diff --git a/t/02renaming.t b/t/02renaming.t new file mode 100644 index 0000000..857b81c --- /dev/null +++ b/t/02renaming.t @@ -0,0 +1,50 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Check renaming imported functions. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + +use strict; +use warnings; +use Test::More tests => 6; + +BEGIN { *note = *diag unless __PACKAGE__->can("note") }; + +use lib qw( examples ../examples ); + +note "Rename functions using -as"; do { + package Local::AAA; + use Example::Exporter fib => { -as => 'fibonacci' }; + ::is fibonacci(6), 8, 'Correctly imported "fibonacci" from Example::Exporter'; + ::ok !__PACKAGE__->can('fib'), 'Did not inadvertantly import "fib"'; +}; + +note "Rename functions using -prefix"; do { + package Local::BBB; + use Example::Exporter fib => { -prefix => 'my' }; + ::is myfib(6), 8, 'Correctly imported "myfib" from Example::Exporter'; + ::ok !__PACKAGE__->can('fib'), 'Did not inadvertantly import "fib"'; +}; + +note "Rename functions using -suffix"; do { + package Local::CCC; + use Example::Exporter fib => { -suffix => 'onacci' }; + ::is fibonacci(6), 8, 'Correctly imported "fibonacci" from Example::Exporter'; + ::ok !__PACKAGE__->can('fib'), 'Did not inadvertantly import "fib"'; +}; + diff --git a/t/03generators.t b/t/03generators.t new file mode 100644 index 0000000..1f69d10 --- /dev/null +++ b/t/03generators.t @@ -0,0 +1,38 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Check renaming imported functions. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + +use strict; +use warnings; +use Test::More tests => 4; + +use lib qw( examples ../examples ); + +use Example::Exporter + embiggen => {}, + embiggen => { -suffix => '_by_2', amount => 2 }, + embiggen => { -suffix => '_by_42', amount => 42 }; + +is embiggen(10), 11, 'embiggen'; +is embiggen_by_2(10), 12, 'embiggen_by_2'; +is embiggen_by_42(10), 52, 'embiggen_by_42'; + +is prototype(\&embiggen), '$', 'correct prototype'; + diff --git a/t/04into.t b/t/04into.t new file mode 100644 index 0000000..d621fef --- /dev/null +++ b/t/04into.t @@ -0,0 +1,36 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Check the C<< -into >> option works. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2013 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + +use strict; +use warnings; +use Test::More tests => 2; + +use lib qw( examples ../examples ); + +{ + package Foo; + use Example::Exporter { into => "Bar" }, qw( fib ); +} + +{ package Bar; } + +ok( not "Foo"->can("fib") ); +ok( "Bar"->can("fib") ); diff --git a/t/05shiny.t b/t/05shiny.t new file mode 100644 index 0000000..9b5875d --- /dev/null +++ b/t/05shiny.t @@ -0,0 +1,40 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Very basic Exporter::Shiny test. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + + +=cut + +use strict; +use warnings; +use Test::More tests => 1; + +{ + package Local::Foo; + use Exporter::Shiny qw(foo bar); + sub foo { + return 42; + } + sub bar { + return 666; + } +} + +use Local::Foo qw(foo); + +is(foo(), 42); diff --git a/t/06notwant.t b/t/06notwant.t new file mode 100644 index 0000000..992bbd7 --- /dev/null +++ b/t/06notwant.t @@ -0,0 +1,41 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Test the C<< !notwant >> notation. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + + +=cut + +use strict; +use warnings; +use Test::More tests => 1; + +{ + package Local::Foo; + use Exporter::Shiny qw(foo bar); + sub foo { + return 42; + } + sub bar { + return 666; + } +} + +my %imported; +'Local::Foo'->import({ into => \%imported }, qw( -all !foo )); + +is_deeply([sort keys %imported], ['bar']); diff --git a/t/07regexp.t b/t/07regexp.t new file mode 100644 index 0000000..998dc4e --- /dev/null +++ b/t/07regexp.t @@ -0,0 +1,48 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Test the C<< /regexp/ >> notation. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + + +=cut + +use strict; +use warnings; +use Test::More tests => 2; + +{ + package Local::Foo; + use Exporter::Shiny qw(foo bar); + sub foo { + return 42; + } + sub bar { + return 666; + } +} + +{ + my %imported; + 'Local::Foo'->import({ into => \%imported }, qw( /^F/i )); + is_deeply([sort keys %imported], ['foo']); +} + +{ + my %imported; + 'Local::Foo'->import({ into => \%imported }, qw( -all !/^F/i )); + is_deeply([sort keys %imported], ['bar']); +} diff --git a/t/08tags.t b/t/08tags.t new file mode 100644 index 0000000..036dc3b --- /dev/null +++ b/t/08tags.t @@ -0,0 +1,66 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Test that tag expansion works sanely. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + + +=cut + +use strict; +use warnings; +use Test::More tests => 7; + +BEGIN { + package Local::Foo; + use Exporter::Shiny qw(foo bar); + our %EXPORT_TAGS = ( + first => [ 'foo' => { xxx => 41 }, 'bar' ], + second => [ 'foo', 'bar' ], + upper => [ + 'foo' => { -as => 'O', -prefix => 'F', -suffix => 'O' }, + 'bar' => { -as => 'A', -prefix => 'B', -suffix => 'R' }, + ], + ); + sub _generate_foo { + my $me = shift; + my ($name, $args) = @_; + return sub () { $args->{xxx} }; + } + sub _generate_bar { + my $me = shift; + my ($name, $args) = @_; + return sub () { $args->{xxx} }; + } +}; + +use Local::Foo + -first => { -prefix => 'first_' }, + -second => { -prefix => 'second_', xxx => 666 }, + -first => { -prefix => 'third_', xxx => 42 }; + +is(first_foo, 41); +is(first_bar, undef); + +is(second_foo, 666); +is(second_bar, 666); + +is(third_foo, 42); +is(third_bar, 42); + +use Local::Foo -upper => { -prefix => 'MY', xxx => 999 }; + +is(MYFOO, 999); diff --git a/t/09warnings.t b/t/09warnings.t new file mode 100644 index 0000000..72d40f3 --- /dev/null +++ b/t/09warnings.t @@ -0,0 +1,83 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Test sub redefinition warnings/errors. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + + +=cut + +use strict; +use warnings; +use Test::More; + +BEGIN { + eval "use Test::Fatal; use Test::Warnings qw(warning :no_end_test); 1" + or plan skip_all => "test requires Test::Warnings and Test::Fatal"; + + plan tests => 4; +}; + +BEGIN { + package Local::Exporter; + use Exporter::Shiny qw(foo bar); + sub foo { 666 } + sub bar { 999 } +}; + +like( + warning { eval q{ + package Local::Test1; + sub foo { 42 } + use Local::Exporter -all; + 1; + } }, + qr/^Overwriting existing sub 'Local::Test1::foo' with sub 'foo' exported by Local::Exporter/, + 'warning about overwriting sub', +); + +like( + exception { eval q{ + package Local::Test2; + sub foo { 42 } + use Local::Exporter { replace => 'die' }, -all; + 1; + } or die $@ }, + qr/^Refusing to overwrite existing sub 'Local::Test2::foo' with sub 'foo' exported by Local::Exporter/, + '... which can be fatalized', +); + +is_deeply( + warning { eval q{ + package Local::Test3; + sub foo { 42 } + use Local::Exporter { replace => 'die' }, -all; + 1; + } }, + [], + '... or suppressed', +); + +is_deeply( + warning { eval q{ + package Local::Test4; + use Local::Exporter -all; + use Local::Exporter qw(foo); + 1; + } }, + [], + 'but importing the exact same sub twice is OK', +); diff --git a/t/10no.t b/t/10no.t new file mode 100644 index 0000000..66b0f82 --- /dev/null +++ b/t/10no.t @@ -0,0 +1,54 @@ +=pod + +=encoding utf-8 + +=head1 PURPOSE + +Check C<< unimport >> works. + +=head1 AUTHOR + +Toby Inkster E<lt>tobyink@cpan.orgE<gt>. + +=head1 COPYRIGHT AND LICENCE + +This software is copyright (c) 2014 by Toby Inkster. + +This is free software; you can redistribute it and/or modify it under +the same terms as the Perl 5 programming language system itself. + +=cut + +use strict; +use warnings; +use Test::More tests => 7; + +use lib qw( examples ../examples ); + +{ + package Local::Pkg1; + use Example::Exporter; + ::is( fib(6), 8, 'fib exported' ); + no Example::Exporter; +} + +ok( !Local::Pkg1->can('fib'), 'tidied fib' ); + +{ + package Local::Pkg2; + use Example::Exporter fib => { -as => 'fibo' }; + ::is( fibo(6), 8, 'fibo exported' ); + no Example::Exporter; +} + +ok( !Local::Pkg2->can('fibo'), 'tidied fibo' ); + +{ + package Local::Pkg3; + use Example::Exporter -all; + ::is( fib(6), 8, 'fib exported' ); + ::is( embiggen(6), 7, 'embiggen exported' ); + no Example::Exporter qw( /^F/i ); +} + +ok( Local::Pkg3->can('embiggen') && !Local::Pkg3->can('fib'), 'tidied by regexp' ); |