Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Dealing with package version numbers when monkey-punching

by MikeTaylor (Acolyte)
on Sep 17, 2020 at 17:20 UTC ( #11121879=perlquestion: print w/replies, xml ) Need Help??

MikeTaylor has asked for the wisdom of the Perl Monks concerning the following question:

I maintain two Perl modules, Net::Z3950::SimpleServer and Net::Z3950::FOLIO.

The former defines classes for a bunch of node-types which together represent a parsed query — things like Net::Z3950::RPN::Term, Net::Z3950::RPN::And, and so on. The latter enhances the functionality of these classes by adding extra methods — a technique I have seen referred to as "monkey-punching", though if there is a more Perlish name for it I would like to be enlightened.

My problem: SimpleServer is at version 1.21. When I try to publish the newer FOLIO module on CPAN, which is at version 1.0, it is rejected with error messages like:

     module : Net::Z3950::RPN::And
     version: 1.0
     in file: Net-Z3950-FOLIO-1.0/lib/Net/Z3950/FOLIO.pm
     status : Not indexed because
             Net-Z3950-SimpleServer-1.21/SimpleServer.pm in
             M/MI/MIRK/Net-Z3950-SimpleServer-1.21.tar.gz has a higher
             version number (1.21)
How can I specify in the FOLIO module that I am not trying to define these classes, only add new methods? And so tell CPAN that I am not trying to provide alternative definitions.

Thank you!

Replies are listed 'Best First'.
Re: Dealing with package version numbers when monkey-punching
by haukex (Archbishop) on Sep 17, 2020 at 17:40 UTC
    a technique I have seen referred to as "monkey-punching"

    Uh, I think you mean monkey-patching... though that doesn't seem to be what you're doing here, by your explanation you seem to be subclassing your modules?

    My problem: SimpleServer is at version 1.21. When I try to publish the newer FOLIO module on CPAN, which is at version 1.0 ... How can I specify in the FOLIO module that I am not trying to define these classes, only add new methods? And so tell CPAN that I am not trying to provide alternative definitions.

    CPAN does not care about the contents of the classes and whether you're trying to add or remove methods, or even if the code stays exactly the same. You must increment the version number for CPAN to recognize that the module is a newer version.

    The problem appears to be you've duplicated package names across your distros, for example, you've got Net::Z3950::RPN::And in both Net-Z3950-SimpleServer and Net-Z3950-FOLIO. This is not a good idea because it will almost certainly conflict somewhere. Instead, subclasses need to have different names.

    On the other hand, since the aforementioned conflicting classes all happen within SimpleServer.pm and FOLIO.pm, it appears these classes could be internal and not user-facing? In that case, there is another solution you could try: hide these packages from the PAUSE indexer. This does not prevent potential conflicts in the code, but it might appease the PAUSE indexer.

      No, I am not subclassing, I am definitely monkey-patching (which, you are right, is the correct term: I was conflating monkey-patching with duck-punching).

      Hiding the packages from the PAUSE indexer was the right solution: many thanks for the link to the article about that. You can see the change that solved my problem at https://github.com/folio-org/Net-Z3950-FOLIO/commit/ef85a1dc127c0770dc7ad17d778fbce64a8e67af if interested. Thanks again.

        I had to take a look at the wiki for monkey patch, and it was worth the read. In the first footnote:

        Duck Punching in JavaScript". Medium. Retrieved 2020-07-12.
        monkey punching - made my day and I think I might have to conflate this term myself. LOL.
Re: Dealing with package version numbers when monkey-punching
by tobyink (Canon) on Sep 18, 2020 at 10:33 UTC

    A neat way to do it would be to use roles. Say, for example, you want to monkey-patch "Example::Module". Then you'd publish your patch like this:

    # lib/Example/Module/Enhanced.pm use 5.008009; use strict; use warnings; package Example::Module::Enhanced; use constant PATCH => __PACKAGE__ . '::Trait'; use constant TARGET => 'Example::Module'; sub import { my ( $me, $arg ) = @_; 'Role::Tiny'->apply_roles_to_package( $me->TARGET, $me->PATCH ) if defined($arg) && $arg eq '-auto'; } sub patch_object { my ( $me, $obj ) = @_; 'Role::Tiny'->apply_roles_to_object( $obj, $me->PATCH ); return $obj; } # Yes, it's safe to define this second package in the same file... package Example::Module::Enhanced::Trait; use Role::Tiny; sub some_new_method { my ( $self, @args ) = @_; ... } around some_existing_method => sub { my ( $orig, $self, @args ) = @_; ...; my $result = $self->$orig( @args ); # call original method from Ex +ample::Module ...; return $result; }; 1;

    With a patch like that, people have two ways of using it. They can use it selectively:

    use Example::Module; use Example::Module::Enhanced; my $obj = Example::Module->new; my $obj2 = Example::Module->new; Example::Module::Enhanced->patch_object( $obj ); # Now $obj1 has your monkey patch, but $obj2 is still non-patched!!!

    Or they can use it everywhere:

    use Example::Module; use Example::Module::Enhanced -auto; my $obj = Example::Module->new; my $obj2 = Example::Module->new; # All Example::Module objects are monkey-patched!

    Note that you're not uploading any modules or packages named Example::Module. So there shouldn't be any versioning/permissions issues with your upload.

    Above code is untested, but should work.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11121879]
Approved by marto
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2023-11-29 11:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?