http://qs1969.pair.com?node_id=11133671

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

I'm having a problem doing perl -c on files which use Attributes.

The error messages are like Invalid CODE attributes: Chained('/') : PathPart('foo') : CaptureArgs('0') because of the Attributes used in some subs in the file.

I understand this is something to do with Moose and a somewhat experimental feature?

Is what I need some other command flag to add to my perl -c command? Or is there some library I can include with -I when I run the syntax check, which will whitelist this feature? Or really just any way to get past this issue and find more low-level problems like a missing comma.

TIA

Replies are listed 'Best First'.
Re: How to syntax-check Catalyst code which throws 'Invalid CODE attributes' errors?
by Your Mother (Archbishop) on Jun 09, 2021 at 04:23 UTC

    It’s not Moose, it’s specifically Catalyst’s handling of the information. Probably your Catalyst code is either wonky or relies on the presence of the base packages to already be loaded in such a way that sub packages will fail because they are missing dependent information. Compare these two–

    perl -c -e 'sub taco :Chained("/") :PathPart("foo") : CaptureArgs(0) { +}' Invalid CODE attributes: Chained("/") : PathPart("foo") : CaptureArgs( +0) at -e line 1. BEGIN failed--compilation aborted at -e line 1.
    perl -c -e 'use parent "Catalyst::Controller"; sub taco :Chained("/") +:PathPart("foo") : CaptureArgs(0) {}' -e syntax OK

    Side-note about the -c flag. It’s not just a syntax check, it has to compile code and that means running some of it and there is no way to know what that might include without stepping through it. For example–

    # emacs/vi UseMe.pm package UseMe; print STDERR "rm -rf /"; perl -c UseMe.pm UseMe.pm syntax OK perl -c -e 'use UseMe' rm -rf /-e syntax OK

      That looks like exactly what I need, thank you. However I'm not quite understanding how I would use your inline example in my real-life situation, where I'm doing something like this:

      perl -I /some/path/perl5 -c Path/To/lib/Controller/Foo.pm

      How can I include your use parent code in that command?

        You can do that but I think you’re probably going to be happier testing the application itself instead of components; or testing the components from within the application. Controllers need to have a notion of the Catalyst context. Essentially, they don’t even properly exist except as part of a request dispatch. A controller endpoint cannot naturally do anything outside of that.

        What you’re doing is akin to trying to check subs inside a script instead of the script itself. It can be done but it’s weird given the, well, context of the code. Catalyst controllers aren’t code that can be run alone, only within and by the app. Side-note: models and views differ here. Catalyst only adds configuration and access affordances for those.

        Catalyst testing is really extremely good and flexible. Only Mojo is better, easier. It doesn’t require any (system, standalone, external) server or special environment or anything.

Re: How to syntax-check Catalyst code which throws 'Invalid CODE attributes' errors?
by syphilis (Archbishop) on Jun 09, 2021 at 03:33 UTC
    Or really just any way to get past this issue and find more low-level problems like a missing comma

    I don't know if it will work, but maybe try temporarily replacing use attributes; with require attributes;, or even try #use attributes; (ie comment it out).

    Cheers,
    Rob

      Thanks but the use of Attributes almost certainly isn't flagged in the particular file I'm testing at any given time, it's a .pm file in a big Catalyst application and would be inheriting the attributes thing from Moose (or possibly Moo?).

        Thanks but the use of Attributes almost certainly isn't flagged in the particular file I'm testing at any given time

        Aaaah ... that could make the hack somewhat cumbersome to implement ;-)
        Sorry for the noise.

        Cheers,
        Rob
Re: How to syntax-check Catalyst code which throws 'Invalid CODE attributes' errors?
by bliako (Monsignor) on Jun 09, 2021 at 07:05 UTC

    Nuke the Attributes pragma.

    echo "package Attributes;1" > /tmp/Attributes.pm perl -c -I/tmp file-to-test.pl

    5' EDIT: I don't know Catalyst or Moose, so if it's attributes you meant, just lowercase the above. And make sure -I/tmp is before any other -I

    Update:

    # file ./strict.pm package strict;1
    perl -I. -Mstrict -e '$x=42' perl -Mstrict -e '$x=42' ouch!

    bw, bliako

      Great! That did it, thanks so much.

      Lower case 'attributes' is what was required, for the record.

        That’s punting a class of Catalyst errors though. Perl allows weird syntax in the “attributes” slot so you’ll only know if they’re bug-free if they go through Catalyst. I would always recommend using regular TAP style testing too. Every time you stray from standard practices you accrue unnecessary technical debt.

        Example tests–

        #!/usr/bin/env perl use strict; use warnings; use Test::More; use Catalyst::Test "MyApp"; # Closest to what you’re already doing. use_ok "MyApp::Controller::Foo"; # More what I would suggest because it’s testing how the # code is called and what it truly does. ok request("/foo")->is_success, "GET /foo is successful"; done_testing(2);

        To get a full list of the action/path endpoints you might want to test, like /foo above, you can run–

        env CATALYST_DEBUG=1 ./script/myapp_server.pl

        You might have trouble if you have tightly coupled models or something. It’s easy to change the configuration to mock/test DBs though. The common way, but your app might not be set up that way, is to have a myapp_test.yml/myapp_test.conf file that overrides the production/deployment models or config (in myapp.yml/myapp.conf).