Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
ashgromnies
Jun 19, 2004

Z-Bo posted:

Have any Perl folks read the book Perl Medic? If so, I was wondering what you thought of it. I read a book review for Perl Medic at TechBookReviews and they claimed it was "highly recommended".

Nope, but that review convinced me to buy it, after maintaining a shitload of legacy perl code.

Adbot
ADBOT LOVES YOU

ashgromnies
Jun 19, 2004

Triple Tech posted:

1) How do you feel about Perl6? I saw a Google Video of Audrey's talk to a Japanese audience and it was pretty amazing. It was a really good presentation and I'm absolutely sold on Perl6. I'm a believer! I think if I knew more about what was required to contribute, I would. But I won't speak Haskellese or whatever.


I'm just unsure if perl6 will be released in time to be useful - they've been developing it since, what, 2000? So many other dynamic languages have been picking up speed and getting massive developer support - perl6 looks very cool, but I don't know how well it will fare since it seems like new projects written in perl are becoming less common and it's being used more to maintain legacy code.

Just my $.02

ashgromnies
Jun 19, 2004

Satan's Scallion posted:

Perl 6 is just so different that it's really a different language altogether. That means it has to overcome the same inertia to switch that every other language has to overcome today to get people off perl. I guess what I'm saying is, what is keeping me on perl today is what's going to keep me from using perl 6 tomorrow.

Yea, you're right about that. It will all come down to what it does better than other languages people are using.

ashgromnies
Jun 19, 2004

rotor posted:

I'm not aware of any other language making that kind of promise. :colbert:

That sounds interesting, what does he mean exactly? I haven't been keeping up on the Perl6 featureset.

ashgromnies
Jun 19, 2004
Here's an interesting problem someone brought up to me...

He needs to trigger a long-running process via an HTTP request. Since the HTTP request will time out before the process is done, he needs it to run in the background, then have an additional script report on its status.

What I was thinking was fork()ing in the method the HTTP request calls, which would allow the original HTTP method to continue, right?

Then create another method that polls the forked process and have the HTML call that via AJAX and report on the status of the process.


Any ideas? I'm not sure I understand how fork() works correctly, my C/Systems Programming Concepts professor was pretty terrible.

Won't fork() duplicate the entire process the HTTP request runs on, though? So that can't be the right way... hoark.

edit: ooh maybe http://www.stonehenge.com/merlyn/LinuxMag/col39.html

ashgromnies fucked around with this message at 22:28 on Nov 16, 2007

ashgromnies
Jun 19, 2004

more falafel please posted:

Or, if you don't want to have to learn about Ajax, the first HTTP request can just kick it off and send you to a page that monitors the status of the job, with auto-refreshes every so often.

Yes but our Apache server is configured to kill the HTTP request after 30 seconds. The job to be executed takes longer than that.

ashgromnies
Jun 19, 2004
Anyone know how to use glob?

Here's some code. I have a list of glob-type filenames in @attachments(the test I am running with only contains one, "./smoke_test_*" but it could contain any number of them)

Here's the code:

code:
    foreach my $glob(@attachments){
        warn "gonna glob $glob\n";
        my @files = glob($glob);
        # do stuff on @files, doesn't matter right here
    }
Here's the output:
code:
gonna glob ./smoke_test_*
glob failed (child exited with status -1, core dumped) at <scriptname> line 227, <_GEN_0> chunk 1.
Line 227 of the script is the
code:
my @files = glob($glob);
line so it fails on that for some reason and I can't tell why. $glob obviously = "./smoke_test_*" which should be a valid glob expandable filename, right?

ashgromnies
Jun 19, 2004

Triple Tech posted:

You should try a one-liner first, like
code:
my @a = glob('*.pl'); print "@a";
If that doesn't work, well, then you're boned.

Nope, I get
code:
glob failed (child exited with status -1, core dumped)
for the code you posted. WTF does that mean

ashgromnies
Jun 19, 2004

Triple Tech posted:

I'm trying to look up more about it, but off the top of my head, I can't help but think that there's something wrong with your perl. What version are you using? And what OS are you running?

You could reimplement the glob concept by just using readdir.

Edit: I think older versions of Perl outsource their globbing to the shell. So if there's something wacky about the environment you're running, that might be it.

I am using perl, v5.6.2 built for i686-linux.


EDIT: Removing "use File::Glob;" from my script solved the issue with the glob('*.pl') not working, but I still can't glob a string and it doesn't spew any errors.

code:
    foreach my $glob(@attachments){
        chomp $glob;
        warn "gonna glob \"$glob\"\n";
        my @files = glob("$glob"); print "@files";
    }
results
code:
gonna glob "./smoke_test_*"
EDIT:
removing the quotes in glob("$glob"); fixed it

loving perl

ashgromnies fucked around with this message at 21:35 on Dec 17, 2007

ashgromnies
Jun 19, 2004

Twlight posted:

I've only just started using perl, I know thats from CPAN and I know how to install things from CPAN, but I have no idea how this works.

What don't you understand exactly? The perldoc is pretty explanatory...

You configure various handlers for when the parser finds different things(like the start of a config block, end of a config block, etc.) then tell it to parse a file and it will run the custom callback handlers you created when it needs to.

ashgromnies
Jun 19, 2004

Fenderbender posted:

Most any application/module/plugin developed at a company is going to be an IP, even small things like a slightly more specific text parser. Everywhere I've worked has used their own namespace, and even namespaces specific to each individual group. It just adds one more layer of structure, in my opinion, and I see no reason to be rid of the practice.

Plus it keeps knowledge sharing a little easier - if you have a namespace specifically for the company, you know where to look for modules related to company or product-specific business logic.

ashgromnies
Jun 19, 2004

mdxi posted:

I can't say for sure, but I think what you might have there is a source tarball, since you seem to indicate that it's not ActivePerl. You might be interested in Strawberry Perl, which is created and maintained by one of the Perl community's most dedicated hackers.

I find it much easier to install Cygwin with the perl runtimes and your editor of choice(vi is pretty nice for perl). Windows-native perl is kind of difficult to work with due to the lack of a strong command-line.

ashgromnies
Jun 19, 2004

mdxi posted:

That's exactly the purpose of the Strawberry Perl distro; it obviates the need to install Cygwin, or anything else. It's a fully self-contained Perl for Windows :)

Hmmm. Rereading your comment, I realize that you might be talking about perl-as-system-glue and not simply perl-the-language, in which case I'm sure you would want Cygwin as well. But if you want Just Perl, you don't need to fiddle with Cygwin installs anymore. I just wanted to point out that Strawberry Perl can act as a standalone distro because there has been some confusion about that issue in the past week as people's interest has been piqued due to the 5.10 accouncements.

I just think it's much easier to deal with perl when you have a nice command line to fall back on.

ashgromnies
Jun 19, 2004
I've been using Catalyst for an app at work recently and I really like the regular expression matching for Controller routines...

code:
sub focus : Regex('^report/focus/([^/]*)/([^/]*)/?([^/]*)?$') {
so cool!

ashgromnies
Jun 19, 2004

Sartak posted:

Here's a good example of why I shouldn't be allowed near Perl's inner workings: autobox::Closure::Attributes

Other than being a neat trick, it is a concise example of how to use really powerful tools you don't see every day:
  • autobox to let you add methods to ordinary scalars (in this case, coderefs)
  • PadWalker to inspect and change the variables captured by a closure
  • AUTOLOAD to catch all method calls
Are there any languages that have anything like this?

What the hell is a closure? I read your example and didn't understand WTF was going on and I'm most of my way through a CS degree.

ashgromnies
Jun 19, 2004
I need some help with Catalyst exception handling.

I have some error checking in my model that causes a die() to raise. I need to catch that somewhere else and depending on the view they have selected, give a different error page.

That is, I have two views - JSON view for AJAX stuff and TT2 view for regular HTML. If it's HTML, sure, show the default error page for now, if view == JSON then put an error message in the JSON output so it doesn't break their browser.


Here's my Root controller's end method:

code:
sub end : ActionClass('RenderView') {
    my ($self, $c) = @_;

    $c->log->debug("IN END METHOD");

    if ($c->req->param('output') && $c->req->param('output') eq 'json'){ # they requested JSON out
        $c->forward( 'MyApp::View::JSON' );
    } else {
        $c->forward( 'MyApp::View::TT' ) # else use TT
        unless ( $c->res->body || !$c->stash->{template} ); # unless they force the body...
    }
}
and when the die occurs, the "IN END METHOD" comes up, but it doesn't perform the JSON output on error even if ?output=json is set. The JSON output works everywhere else except when an exception is raised from die().

Log output:

code:
[debug] IN END METHOD
[error] Caught exception in MyApp::Controller::MyController->perform_roll "ERROR::: my error message at /lib/MyApp/Model/MyModel.pm line 184."
[info] Request took 4.181835s (0.239/s)
.----------------------------------------------------------------+-----------.
| Action                                                         | Time      |
+----------------------------------------------------------------+-----------+
| /auto                                                          | 0.003481s |
| /promotions/perform_roll                                       | 4.119870s |
| /end                                                           | 0.004715s |
|  -> MyApp::View::JSON->process                                 | 0.000783s |
'----------------------------------------------------------------+-----------'
It looks like it is calling the JSON view but the client's browser receives back an HTML error page from the AJAX request.


Ideas?

ashgromnies
Jun 19, 2004

genericadmin posted:

By default Catalyst will check $c->error at the end of a request and show its goofy error page. To override the default error handler, you need to check $c->error yourself (usually in MyApp::end()).

I ended up throwing an eval{ }; around the call and got it working with my custom error handling.


Okay, another Catalyst question...


I have a method triggered that runs in the background(I enabled multi-threading on my Catalyst app) that takes a little bit of time to perform and has multiple actions it performs. I would like to inform the user of the current status of this method.


Here's the code that I have...

code:
    my $callback = sub {
        warn "logging status ".$_[0];
        $c->session->{'roll_status'} = $_[0];
    };

    if (eval { $somemodel->perform_action($params,
      $callback) }) {
        # action performed successfully
        $c->stash->{'json_status'} = SUCCESS;

    } else {
        # action failed
        $c->log->debug("error occured during perform_action");
        $c->stash->{'json_status'} = $@;
    }
$repo is a model object... then in perform_action, it looks something like this...

code:
sub perform_action {
    my $self = shift;
    my ($params, $status_callback) = @_;

    # some work is done here that takes a few seconds
    $status_callback('doing step 1');

    # other stuff that takes a few seconds
    $status_callback('doing step 2');

    # more more more stuff that takes a few seconds
    $status_callback('doing step 3');

    # last bit of work done...
    $status_callback('Done!');

    return 1;
}
So when I watch my logs, I see...

code:
logging status doing step 1
logging status doing step 2
logging status doing step 3
logging status Done!
occur one after another every few seconds as the code runs, as I would expect.

So then I have this method to check the status...

code:
sub get_roll_status : Regexp('^([^\/]+)\/get_roll_status$') {
    my $self = shift;
    my ($c) = @_;


    $c->stash->{'json_roll_status'} = $c->session->{'roll_status'};
    $c->stash->{'template'} = 'rolltool/roll_status.tt2';
}
and it ALWAYS returns "Done!" no matter what step is currently underway. From what I can tell, Catalyst waits to set the session variables until the entire request is complete, then does them all at once. The same behavior is exhibited if, instead of warn I use $c->log->debug(); statements... nothing appears while the work is being done, then once it is done it prints out all the statuses at once.


What would you do to get around this? I could write the status to a file locally and read from that but that seems to go against the Catalyst-way.

ashgromnies
Jun 19, 2004

genericadmin posted:

What are you accomplishing by using threads? It seems like a job queue might be a better fit for what you are trying to do. Have the worker update the job status as it processes it, then just let your Catalyst action query the job status. This has the benefit of being asynchronous.

We can't have a JobQueue because multiple people are allowed to trigger this action to happen at once and that is perfectly fine and expected. With a JobQueue, it is feasible that things might get out of order and new data could be stamped on with old data - the way it's set up now, it will throw an error if multiple people trigger actions that step on eachother, which is intended.

So I need to find a way of doing this without a slow Queue. It needs to allow multiple requests from different people at once...

ashgromnies
Jun 19, 2004
So no one knows how to get around the fact that Catalyst writes out session variables at the end of the request? I tried using a Cache, that didn't work either :(

ashgromnies
Jun 19, 2004

genericadmin posted:

Sessions are implemented as plugins (last I had seen anyway), so you are bound by the plugin implementation and the various Catalyst phases.

The intent of a "session" is to preserve state between HTTP messages, not within one request, so it should not be an issue when the session state is committed. I suspect you may be using the wrong tool for the job, but to be honest I'm not sure I'm correctly discerning exactly what you are wanting to do (maybe that's why others are not responding).

Adding threading to an application greatly affects how MVC should be applied.

For what it's worth, using Cache::FastMmap and $c->cache->get and set worked.

ashgromnies
Jun 19, 2004
I'm trying to write a one liner to validate that all the *.yml files it finds can be properly parsed...

Here's what I came up with:

code:
find / -type f | grep ".yml" | xargs perl -e 'use YAML qw"LoadFile"; eval{ LoadFile("$_"); }; print "$_ : $@\n" if ($@);'
however it's not working.

It only gets two arguments, which I can check with:

code:
-bash-3.1$ find / -type f | grep ".yml" | xargs perl -e 'use YAML qw"LoadFile"; eval{ LoadFile("$_") if $_; }; print "$_ : $@\n";'
 :
 :
but that doesn't make sense. If I just run

code:
find / -type f | grep ".yml"
I get a huge list of files returned - what am I doing wrong?


edit: closer
code:
find / -type f | grep ".yml" | xargs perl -ne 'use YAML qw"LoadFile"; for(@ARGV){ eval{ LoadFile("$_"); }; print "$_ : $@\n" if ($@);}'
this one doesn't work, I get a lot of errors like:

code:
/path/to/._some_file_with_underscore_and_._.yml : YAML Error: Invalid characters in stream. This parser only supports printable ASCII
   Code: YAML_PARSE_ERR_BAD_CHARS
   Line: 0
   Document: 0
 at /opt/ActivePerl-5.8/site/lib/YAML.pm line 33
I'm pretty sure it's due to either the period or the underscore because files without those are parsing just fine.

perl one liners are fun but I write them like a regular script :(

ashgromnies fucked around with this message at 15:02 on Mar 14, 2008

ashgromnies
Jun 19, 2004

genericadmin posted:

How about this?

code:
find . -regex '.*\.yml$' -type f -print0 |xargs -0 perl -mYAML -e 'eval { YAML::LoadFile($_); 1; } or warn "fail: $_\n\t$@" for(@ARGV);'

Awesome, thanks! How is it you know everything?

I went with this to exclude files that start with a "."... there were these "._.*.yml" files that seemed to be Mac OS X binary temp files that contained no valid YAML serialization:

code:
find / -regex '.*\/[^\.][^\/]*\.yml$' -type f -print0 |xargs -0 perl -mYAML -e 'eval { YAML::LoadFile($_); 1; } or warn "fail: $_\n\t$@" for(@ARGV);'

ashgromnies fucked around with this message at 20:19 on Mar 14, 2008

ashgromnies
Jun 19, 2004

yaoi prophet posted:

I've been doing some dangerous mucking around (too much reading source code to Damian Conway modules...). I actually got a module working which enables this syntax:

code:
    sub my_func :Arguments(String, OneOf(Int, String(xyz), Instance(File))) {
        print "yarr!\n";
    }


    my_func('foo', 'bar');
When run...

code:
 "bar" for argument 2 of main::my_func() is invalid, must be one of: a valid integer, a scalar string matching /xyz/, an instance of File() at ArgumentValidator.pm:665
  at main::my_func('foo', 'bar')  (args.pl:13)
It's only run-time checking, of course, but it's an interesting (ab)use of subroutine attributes.

The fact that perl lets me pull this off is sort of simultaneously entertaining and frightening.

Perl is really cool. I'm a big fan of AUTOLOAD
http://64.233.167.104/search?q=cach...lient=firefox-a

ashgromnies
Jun 19, 2004

Narpas posted:

Well, I knew, academically, about making a hash table, but I didn't realize they were implemented simply - I've always figured that they were needlessly complex for small scale tasks.

perl, along with most modern scripting languages, implements hash tables as a core data type.

Also, I would recommend that you take an md5 checksum of the file instead of checking its size to see if they're the same - it's possible that two files have the same filesize but different contents.

ashgromnies
Jun 19, 2004
Okay, I've been pounding my head against this for like an hour and I don't know what I'm doing wrong.

I'm trying to use SOAP::Lite to create a SOAP formatted response, that needs to contain a relatively simple series of elements.

Basically, there needs to be a status and then an element named history, which is an array of elements named pointHistory that are of type PointHistory. Yeah, making the names and types so similar is confusing.

Here's an example of what it should look like:

XML for example, not SOAP but you get the point...
code:
<getPointHistoryResponse>
	<status>1</status>
	<history>
		<pointHistory>
			<description>description 1</description>
			<date>2008-01-02 23:45:00</date>
			<points>200</points>
		</pointHistory>
		<pointHistory>
			<description>description 2</description>
			<date>2008-01-03 23:44:01</date>
			<points>250</points>
		</pointHistory>
	</history>
</getPointHistoryResponse>
(element names don't need to be EXACT since the client side hasn't been finalized yet)

Here's what I'm getting back right now:

code:
		<namesp1:pointHistoryResponse xmlns:namesp1="http://myns.com">
			<status xsi:type="xsd:int">1</status>
			<history xsi:type="tns1:ArrayOfPointHistory">
				<description xsi:type="xsd:string">description 1</description>
				<date xsi:type="xsd:string">10-03-06</date>
				<points xsi:type="xsd:int">100</points>
				<description xsi:type="xsd:string">description 2</description>
				<date xsi:type="xsd:string">10-03-06</date>
				<points xsi:type="xsd:int">100</points>
			</history>
		</namesp1:pointHistoryResponse>
As you can see, the histories aren't getting wrapped up in a container element correctly.

Here is the pertinent part of my WSDL:

code:
            <element name="pointHistory">
                <complexType>
                    <sequence>
                        <element name="swid" type="xsd:string"/>
                    </sequence>
                </complexType>
            </element>

            <complexType name="PointHistory">
                <sequence>
                    <element name="description" type="xsd:string"/>
                    <element name="date" type="xsd:string"/>
                    <element name="points" type="xsd:int"/>
                </sequence>
            </complexType>

            <complexType name="ArrayOfPointHistory">
                <complexContent>
                    <restriction base="soapenc:Array">
                        <attribute ref="soapenc:arrayType"
                        wsdl:arrayType="tns1:PointHistory[]"/>
                    </restriction>
                </complexContent>
            </complexType>


            <element name="pointHistoryResponse">
                <complexType>
                    <sequence>
                        <element name="history" type="tns1:ArrayOfPointHistory"/>
                        <element name="status" type="xsd:int"/>
                    </sequence>
                </complexType>
            </element>
And here's the perl code used to generate it:

code:
        my @credit_arr;
        foreach my $credit(@$history){
            my $elem = SOAP::Data->value(
                SOAP::Data->name('pointHistory' =>
                    SOAP::Data->name('description' => $credit->{description})->type('xsd:string'),
                    SOAP::Data->name('date' => $credit->{credit_date})->type('xsd:string'),
                    SOAP::Data->name('points' => $credit->{point_value})->type('xsd:int')
                )
            )->type('tns1:PointHistory');
            push @credit_arr,$elem;
        }

        $soap_return = SOAP::Data->value(
                            SOAP::Data->name('status' => 1)->type('xsd:int'),
                            SOAP::Data->name("history" => \SOAP::Data->value(
                                              SOAP::Data->name("pointHistory" => @credit_arr)
                                                        ->type("tns1:PointHistory"))
                                                   )->type("tns1:ArrayOfPointHistory"),
                      )->attr({xmlns => 'http://myns.com'})->uri('myns.com')->type('pointHistoryResponse');
I honestly have no idea where to go with this now :( I figured that wrapping the description, date, and points with the SOAP::Data->name('pointHistory') object would do it but apparently not. I also have a poor grasp of how SOAP::Data works since this is my first try at using it... what a pain.

ashgromnies
Jun 19, 2004

genericadmin posted:

1) $elem may not be getting what you think (list of individual nodes), and you're dumping that here via list context. How about using the SOAP::Data->name('thing')->value(); form instead?


It does seem to be getting what I want, it even shows it being enclosed in an element named pointHistory. Making that change didn't affect the results.


genericadmin posted:

2) I think you are wanting to supply SOAP::Data->name("history") with a list of "pointHistory" nodes, but it looks like you are supplying just one with @credit_arr as its value/children.


@credit_arr is an array of PointHistory nodes when I Data::Dumper it.

genericadmin posted:

Either way, bust out Data::Dumper, check out what is going into $elem & @credit_arr and have a look at the SOAP::Lite source and make sure those methods expect/return what you expect. I only glanced, but the docs seem to suck.

Yep, the docs are pretty bad. I have access to the O'Reilly bookshelf and all the books there that reference SOAP::Lite have like two pages where they make a Hello World example and then say, "Have fun!"


EDIT: Ah, fixed it! I needed to replace $elem with:

code:
        my @credit_arr;
        foreach my $credit(@$history){
            my $elem = SOAP::Data->name('pointHistory')->type('tns1:PointHistory')->value(
                    \SOAP::Data->value(
                        SOAP::Data->name('description' => $credit->{description})->type('xsd:string'),
                        SOAP::Data->name('date' => $credit->{credit_date})->type('xsd:string'),
                        SOAP::Data->name('points' => $credit->{point_value})->type('xsd:int')
                    )
            );
            push @credit_arr,$elem;
Surprisingly, I found the answer in "Amazon Hacks" that had a section labeled "Program AWS with SOAP::Lite and Perl". It didn't work after I followed what you said in your first solution because I put the type('tns1:PointHistory') AFTER the value, and I guess it didn't like that.

ashgromnies fucked around with this message at 15:31 on May 23, 2008

ashgromnies
Jun 19, 2004

German Joey posted:

i noticed that they still have a few Perl6 sessions in the program. i mean, for christs sake, who the gently caress still cares about it? its been 8 years now!

One of my coworkers was on the original Topaz Perl 6 project and said that development changed a lot since then - they were making good progress and had a team that fit well together, but other influences changed things and I guess they scrapped a lot of work.

I unfortunately don't know any specifics.

ashgromnies
Jun 19, 2004
I need some assistance from a SOAP::Lite expert.

I am using SOAP::Lite to run a SOAP service. I have a very simple sanity check method and am querying it in soapUI to view its adherence to the WSDL.

I have two servers. One is running SOAP::Lite version 0.69, the other is running 0.60. The server running 0.60 returns the correct data and it validates against the WSDL fine.

The server running 0.69, however, leaves out the xmlns attribute on elements even when I try forcing it which results in it not being able to find their xsi:type in the namespace(from what I understand, SOAP is kind of weird).

I cannot change the version of SOAP::Lite installed, it is out of the question.

Here is the output from version 0.60:

code:
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema">
   <SOAP-ENV:Body>
      <namesp1:sanityCheckResponse xmlns:namesp1="http://soap.mysite.com">
         <status xsi:type="xsd:int" xmlns="http://soap.mysite.com">1</status>
      </namesp1:sanityCheckResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
and version 0.69:

code:
<soap:Envelope soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <sanityCheckResponse xmlns="http://soap.mysite.com">
         <status xsi:type="xsd:int">1</status>
      </sanityCheckResponse>
   </soap:Body>
</soap:Envelope>
Any ideas?

ashgromnies
Jun 19, 2004

Triple Tech posted:

Blegh, I was going to ask for a working example but I think I finally figured it out (in my head...) :pseudo:

Edit: Boo, no, I'm confused.

code:
# does not work
sub asdf { print $a };

my $a = 'boost';
asdf()

#-- works
my $a = 'boost';
sub asdf { print $a };

asdf()

#-- ugh... works
my $a = sub { /boost/ };
{
  local $_ = 'boost';
  print 2 if $a->()
}

Which version of Perl has the lexical $_? My version doesn't.

ashgromnies
Jun 19, 2004
So I am trying to do something that I think should be pretty simple, but it's just not coming to my mind.

I have a reference to an element in an array and I want to completely remove it from the array. How can I delete the array's reference to it without knowing its position in the array? I don't think you can do this with delete.


Ex:

code:
my @arr = ("my", "balogna", "has", "a", "first", "name", "and", "it's", "not", "oscar", "meyer");

foreach my $el(@arr){
    undef $el if $el eq 'not';
}
which obviously won't work the way I want it to - it leaves undef in the array.

Neither does this work correctly...

code:
my @arr = ("my", "balogna", "has", "a", "first", "name", "and", "it's", "not", "oscar", "meyer");

foreach my $el(@arr){
    $el = () if $el eq 'not';
}
Ideas?

edit: of course, I can always follow that loop up with @arr = grep { $_ } @arr to resolve it but I'm looking for something cleaner.

ashgromnies fucked around with this message at 22:14 on Oct 31, 2008

ashgromnies
Jun 19, 2004
Sorry, I should have clarified, I need to do some work on the value. I am passing an array ref recursively to a function, and want to erase elements from it when they've been processed.

Maybe I can explain the entire thing and it will make more sense...

I have a list of directory names belonging to various projects in an array. Every project has a root directory with a special application file in it that lets you know it's the root. Projects may be infinitely nested within eachother.

So what I'm trying to do is find the nearest application file to every directory in the array.

Here's the code I have thusfar:

code:
sub find_application_ymls {
    my ($directories_ref, $application_ymls_ref) = @_;

    # base case - return if no directories left in list
    # to process.
    return if !scalar @{$directories_ref};

    foreach my $dir(@{$directories_ref}){
        my $yml_path = "$dir/application.yml";
        if(-e $yml_path){
            # found one
            push @{$application_ymls_ref}, $yml_path;
            # delete $dir from array
            undef $dir;
        } else {
            # wasn't at this level, go one up
            $dir =~ s/\/[^\/]+$//;
        }       
    }

    # wipe out undef
    @{$directories_ref} = grep { $_ } @{$directories_ref};

    # recurse
    &find_application_ymls($directories_ref, $application_ymls_ref);
}
actually I should really use a hashref for application_ymls_ref to prevent duplicates from appearing.

Anyways, this works, I was just wondering if there's a better way.

ashgromnies
Jun 19, 2004

rjmccall posted:

Don't think of @{$directories_ref} as an array, think of it as a queue:


loving ace. I always forget about queues working in Perl all the time :)

I also didn't know about File::Basename... is there a good core module reference anywhere?

ashgromnies
Jun 19, 2004

Voltaire posted:

I'm having difficulty writing a program that determines whether a 7 character input is a character. I am not allowed to use arrays, reverse, split, join; just basic perl functions.

So far I have

code:
use strict;
use warnings;
use diagnostics;

print "Enter in a 7 character item: ";
chomp (my $input = <> );

$input =~ s/\\s//g;
if ($input = [9,8,7,6,5,4,3,2,1,0] == [0,1,2,3,4,5,6,7,8,9])
{
        print "PALINDROME!\n";
}
else
{
        print "NOT A PALINDROME!\n";
}
Obviously I'm missing something here...

Here's a naive solution for it, purposefully done poorly:

code:
[spoiler]
#!/opt/perl/bin/perl

use strict;
use warnings;

my $str = "banana";

print "is $str palindromic? ".&is_palindrome($str)."\n";

$str = "racecar";

print "is $str palindromic? ".&is_palindrome($str)."\n";


sub is_palindrome {
    my ($str) = @_;
    
    my $orig = $str;
    my $rev;

    while (my $chr = chop $str){
        $rev .= $chr;
    }

    return ($rev eq $orig) ? 1 : 0;
}
[/spoiler]
However, they most likely want you to use regular expressions to solve it.

ashgromnies
Jun 19, 2004
So I am backticking a command and it isn't working. It doesn't die or return a null value, it just hangs and waits for a response - incredibly messed, especially since I can run the exact same command from the command line and it works.

The method with the backticked command lives inside of a package. I recently moved the package from being in the .pl file my script utilizing the package is in into its own .pm file because it got large and I had other packages.

The backticked command worked before, I'm not sure why it wouldn't now. It works if I copy and paste it to the command line and I'm really confused.

Here's the offensive method(pardon the copious ugly logging, it's for debugging right now):
code:
sub _get_revision_info {
    my ($self) = @_;
    
    $self->{debug} && $self->log_activity("getting revision info");
    $self->{debug} && $self->log_activity("$self->{svn} info --non-interactive $self->{checkout_path}");
    [b]my $current_rev_info = `$self->{svn} info --non-interactive $self->{checkout_path}`;[/b]
    $self->{debug} && $self->log_activity($current_rev_info);
    $self->{debug} && $self->log_activity("$self->{svn} info --non-interactive $self->{source}");
    [b]my $remote_svn_info = `$self->{svn} info --non-interactive $self->{source}`;[/b]
    $self->{debug} && $self->log_activity($remote_svn_info);
    
    $current_rev_info =~ m/Revision: ([0-9]*)/;
    $self->{current_rev} = $1;
    
    $remote_svn_info =~ m/Last Changed Rev: ([0-9]*)/;
    $self->{latest_rev} = $1;
    
    $remote_svn_info =~ m/Revision: ([0-9]*)/;
    $self->{newest_rev} = $1;
    
    $self->{debug} && $self->log_activity("current_rev: $self->{current_rev}\nlatest_rev: $self->{latest_rev}\nnewest_rev: $self->{newest_rev}");
}   
Results in:

code:
[2008-11-25 17:35:25-0500] getting revision info
[2008-11-25 17:35:25-0500] /usr/bin/svn info --non-interactive /Users/me/blabla/rolldest
[2008-11-25 17:35:25-0500] Path: /Users/me/blabla/rolldest
URL: [url]https://mysvn.com/svn/some/path[/url]
Repository Root: [url]https://mysvn.com/svn/some[/url]
Repository UUID: 73252f4f-e7c9-4a5b-831e-b5ca1aed9ccc
Revision: 229
Node Kind: directory
Schedule: normal
Last Changed Author: me
Last Changed Rev: 229
Last Changed Date: 2008-11-19 14:49:46 -0500 (Wed, 19 Nov 2008)


[2008-11-25 17:35:25-0500] /usr/bin/svn info --non-interactive [url]https://mysvn.com/svn/some/path[/url]
and then it hangs.

If I execute that `/usr/bin/svn info --non-interactive https://mysvn.com/svn/some/path` on the command line, I get my expected output:

code:
Path: rc
URL: [url]https://mysvn.com/svn/some/path[/url]
Repository Root: [url]https://mysvn.com/svn/some[/url]
Repository UUID: 73252f4f-e7c9-4a5b-831e-b5ca1aed9ccc
Revision: 229
Node Kind: directory
Last Changed Author: me
Last Changed Rev: 229
Last Changed Date: 2008-11-19 14:49:46 -0500 (Wed, 19 Nov 2008)

ashgromnies
Jun 19, 2004

Triple Tech posted:

This probably isn't related (but it couldn't hurt), try putting your debug flag into the log activity subroutine. Also, stick to simple scalars ($just $like $this) for interpolation. And then try again.

Nah, I have logs that should always occur regardless of if I'm in debug mode or not. A $self->log_debug method or similar would be appropriate, though. I'm pretty sure it's not the interpolation of the scalars because the first backticked command runs fine and I get its output in my log.

edit: this what you mean?(logging truncated)

code:
sub _get_revision_info {
    my ($self) = @_;
    
    my $svn = $self->{svn};
    my $checkout_path = $self->{checkout_path};
    my $source = $self->{source};

    my $current_rev_info = `$svn info --non-interactive $checkout_path`;
    my $remote_svn_info = `$svn info --non-interactive $source`;
    
    $current_rev_info =~ m/Revision: ([0-9]*)/;
    $self->{current_rev} = $1;
    
    $remote_svn_info =~ m/Last Changed Rev: ([0-9]*)/;
    $self->{latest_rev} = $1;
    
    $remote_svn_info =~ m/Revision: ([0-9]*)/;
    $self->{newest_rev} = $1;
}   
hung on the second backticked expression as well :(

ashgromnies fucked around with this message at 00:05 on Nov 26, 2008

ashgromnies
Jun 19, 2004

satest4 posted:

What is the value of $svn and $checkout_path? Check that the user perl is running as can resolve and execute the command. If svn is really hanging, try attaching strace to the pid and see what is holding it up.

Also, there are many subversion-related CPAN modules available. ;)

I printed the log above that shows that the backticked commands it tried executing were correct. I am running the script as the same user as I ran them from the command line with.

code:
[2008-11-25 17:35:25-0500] /usr/bin/svn info --non-interactive /Users/me/blabla/rolldest
[2008-11-25 17:35:25-0500] Path: /Users/me/blabla/rolldest 
URL: [url]https://mysvn.com/svn/some/path[/url] 
Repository Root: [url]https://mysvn.com/svn/some[/url] 
Repository UUID: 73252f4f-e7c9-4a5b-831e-b5ca1aed9ccc 
Revision: 229 
Node Kind: directory 
Schedule: normal 
Last Changed Author: me 
Last Changed Rev: 229 
Last Changed Date: 2008-11-19 14:49:46 -0500 (Wed, 19 Nov 2008)
[2008-11-25 17:35:25-0500] /usr/bin/svn info --non-interactive [url]https://mysvn.com/svn/some/path[/url]
Those are the results of the last three log_activity calls that you see and is how I found it's hanging on `/usr/bin/svn info --non-interactive https://mysvn.com/svn/some/path` which should work - if I run that on the command line as the same user, it works just fine and the first backticked expression works and gets the expected output... very confusing.

We have SVN::Client, I was recommended not to use it but I haven't looked into it. Is there anything you've used?

I don't have strace on my Mac, I'll try running this on Linux tomorrow.

ashgromnies fucked around with this message at 05:51 on Nov 26, 2008

ashgromnies
Jun 19, 2004

satest4 posted:

When we used subversion, we'd get information directly from the repo (ie, on the filesystem), because it proved more reliable than using a client (and I avoid CPAN like the plague despite me suggesting it to you :) ).

We switched to Git earlier this year. I like it a lot more than subversion.

Yeah, we use Mercurial for actual development, Subversion is used only as a backend for a specific deployment management application(what I'm working on). Once we feature-freeze a release, we import it into Subversion and then have the ability to use the deployment management software to put it on any of our servers/environments.


edit: hrm, ran it on Linux, same issue with the backtick exists, strace reveals a bunch of spam saying this:

code:
stat("//someconfig.yml", 0x9659140)         = -1 ENOENT (No such file or directory)
stat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
Hrm. Not sure why it would be trying to stat that file.


editx2: So I'm pretty sure it has nothing to do with the backticked expression, it looks like an issue because I wasn't disabling buffering on my logfile so I thought it was halting somewhere that it wasn't... oops.

ashgromnies fucked around with this message at 17:36 on Nov 26, 2008

ashgromnies
Jun 19, 2004

Triple Tech posted:

Someone from #cobol told me the problem I'm trying to solve at work is called "dependency injection", and it seems to be right on the money.

Which would be the least evil way of accessing a hash our'ed by a package? eval or a symbolic reference?

I'm trying to implement what I would call data inheritance... Like the data is structured similarly in all the subclasses, but I don't want to expend the energy (hurf) in creating accessor stubs in each subclass, since they're exactly the same.

Edit: I realize this is a bit all over the place...

Are you sure you're going with the right solution? What are you trying to do this for?

Adbot
ADBOT LOVES YOU

ashgromnies
Jun 19, 2004
One of my coworkers wrote something like this:

code:
#!/usr/bin/env perl

use strict;
use Data::Dumper;

my @arr = ("one", "two");
my $hash_ref = {numbers => {}};

@{$hash_ref->{numbers}}{@arr} = ("uno", "dos");

print Dumper $hash_ref;
in an app and it's pretty cool but I've never seen that notation before.

Specifically, this: @{$hash_ref}{"donkey"} = "rear end";

What the hell is going on there? It will set the "donkey" key in $hash_ref to be "rear end" but... how? I didn't know you could use the {} notation on an array.

  • Locked thread