How does this function return its value? - function

I'm actually scripting and a part of my script is a FTP file download. The code words without any problem, but I don't understand one specific part. Its the only part from the code I haven't written by myself. I understand how the code works, but I actually dont understand how the function return its value. You're may confused what I mean, so let me explain it with a bit of code:
function get-ftp {
try {
$ftprequest = [system.net.ftpwebrequest]::Create($uri)
$ftprequest.Credentials = New-Object system.net.networkcredential($user,$pass)
$ftprequest.Proxy = $null
$ftprequest.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
$ftpresponse = $ftprequest.GetResponse()
$reader = New-Object IO.StreamReader $ftpresponse.GetResponseStream()
$reader.ReadToEnd()
$reader.Close()
$ftpresponse.Close()
}
catch {
Write-host "Error while reading filenames"
}
}
So this is my function to get all directories from the FTP server. I call this function with this code:
$allXmlFiles = get-ftp
So after the call, my $allXmlFiles contains a string (tested with getType on $allXmlFiles) with all the filenames on the server. Now my question: How is the answer from the FTP passed to this variable? There's no return in the function, so I'm quite confused how this works. I tried so take the try/catch out of the function and access the answer directly, but that didin't work. I tried to find it in $reader and in $ftpresponse - no success.
It would be really cool if someone can explain me whats going on here. As said, the code works, but I would like to understand whats going on here.

It's
$reader.ReadToEnd()
StreamReader.ReadToEnd() method outputs string and since it's result is not assigned to variable it will be the function output.
Idiomatic way would be to write it like this:
Write-Output $reader.ReadToEnd()

In PowerShell, the result of every command / statement is returned as output if you don't assign or pipe it to anything.
The return keyword only exits the current scope. You rarely use return in PowerShell.
As beatcracker mentioned, $reader.ReadToEnd() is producing the output.

Related

Groovy no signature of method

I am trying to create a function in Groovy that inputs a string and returns a modified string. The problem I believe is within an addon, which is a specific software environment I am working with i.e. logic.script.Microblock. The error message I am receiving is:
No signature of method: com.controlj.addonsupport.logic.script.Microblock.capAbbreviate() is applicable for argument types: (java.lang.String) values: [OAT Dewpoint bavo].
I have tried dispName = capAbbreviate(dispName.toString()), dispName = capAbbreviate(dispName), and capAbbreviate(dispName).
The software environment is using some sort of addon. I am still fairly new to Groovy/Java so this seems like it could be something simple but it's not clicking in my head just yet.
The code simplified below is:
def exceptions = ['Ac':'AC','Oat':'OAT','Vav':'VAV']
def exceptionNonAlpha = '(?=[^a-zA-Z])'
def dispName
def capAbbreviate(String mbText)
{
// Iterates through 'exceptions' map and finds abbreviations and recapitalizes them
for (hvacName in exceptions.keySet()) {
mbText = mbText.replaceAll(hvacName + exceptionNonAlpha, exceptions[hvacName])
}
return mbText
}
logic.microblocks
{
dispName = prop.'display name'
dispName = capAbbreviate(dispName.toString()) // also tried capAbbreviate(dispName)
println dispName
}
The solution has two parts:
Similar to what #AndrejIstomin mentioned, removing the def to make a list or variable global resolved one part of the issue
The second part to the solution is that this. needed to be used to call the method. i.e. this.capAbbreviate(dispName)

unable to use the data from d3.csv() outside of the .get clause

I can read some data from a csv with d3. It works fine.
d3.csv("myfile.csv")
.get(function(data) {
console.log(data);
});
If I execute this, it prints the data to the console in the expected way. It even recognizes the column headers. But the problem is I'm trying to read a number of csv and json files. Nesting them is ugly, tedious and error prone. So I tried this:
var something;
d3.csv("myfile.csv")
.get(function(data) {
something = data;
});
console.log(something);
The problem is that "something" doesn't have the expected value any more. I figure this has got to be a common thing. How is the handled? (I'm using d3 4.2.8)
Does it work for you?
const doSomething = data => {
console.log(data);
}
d3.csv("myfile.csv").get(doSomething);

JSON decode failed

Following is the code snippet where I am observing error: "malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "(end of string)") at"
Error observed is at the decode_json line. Can someone point out what is the error?
my $serverurl = "http://mycompany.net/rest/api/2/";
my $username = 'my.email#domain.com';
my $password = "mypassword\#2019";
my $i ;
my $test;
my $headers = {Accept => 'application/json', Authorization => 'Basic ' .encode_base64($username . ':' . $password)};
my $client = REST::Client->new();
my $idartinstance;
my $idartinstance1;
if (!$idartinstance)
{
print " Trying to Connect to URL using REST client interface \n\n";
$idartinstance1 = $client->GET($serverurl."serverinfo",$headers);
$idartinstance = decode_json($idartinstance1->responseContent());
}
When I print $idartinstance, I get this:
REST::Client=HASH(0x8682024)->responseContent()
Does this mean, it is not able to find REST client?
[EDIT] I have modified the script as below and no difference in the errors.
my $serverurl = "https://mycompany.net/rest/api/3/";
my $username = 'my.email#domain.com';
my $password = 'pf9fCdkGXmi4pMHiwIh74A0D';
my $headers = {Accept => 'application/json', Authorization => 'Basic ' . encode_base64($username . ':' . $password)};
my $client = REST::Client->new();
if (!$idartinstance)
{
print " Trying to Connect to JIRA using REST client interface \n\n";
$client->GET($serverurl."serverInfo", $headers);
print $client->responseContent();
$idartinstance = decode_json($client->responseContent());
}
Now I have used encoded password. Error is same: malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "(end of string)"). Tried accessing "https://mycompany.net/rest/api/3/serverInfo" via web browser and able to get the details.
Once you get a response, you have to check that its what you want.
if( $client->responseCode() eq '200' ){
print "Success\n";
}
You may also want to check that the content-type is what you expect. If it's supposed to be JSON, check that it is:
if( $client->responseHeader('Content-Type') =~ m|\Aapplication/json\b| ) {
print "Got JSON\n";
}
Once you've established that you have what you wanted, pass the message body off to the JSON decoder.
my $data = decode_json($client->responseContent());
You might also try to catch errors where you should have valid JSON but don't. The block eval can handle that (and see the many sources of the proper employment of eval for its best use):
my $data = eval { decode_json(...) };
I find that I tend to get the wrong content in two situations:
the wrong endpoint, from which a 404 handler returns HTML
a captive portal, which also returns HTML
I think you're misreading the documentation for the module. From the synopsis there, the example that most closely resembles yours is the first one:
my $client = REST::Client->new();
$client->GET('http://example.com/dir/file.xml');
print $client->responseContent();
Notice, in particular, that this example does nothing with the return value from GET(). In your example you do the equivalent of this:
my $client = REST::Client->new();
my $resp = $client->GET('http://example.com/dir/file.xml');
print $resp->responseContent();
As it happens, although there is no documented return value from GET() [Update: I was wrong here - see the first comment - but the return value is really only intended for chaining method calls], it actually returns the object that it was passed, so your approach should work. But it's generally a bad idea to not follow the documentation.
So what is actually going wrong? Well, I'm not sure. As I said, your approach should (accidentally) work. But the error message you're getting tells us that what you're passing to decode_json() is a REST::Client object, not a string containing JSON. I don't think that's how your code should work. Perhaps the code you've shown us isn't actually the code you're running.
The best approach to debug this is to follow the advice from Quentin in the first comment on your question - print the value that you're trying to pass to decode_json() before passing it to the function. In fact, that's good general programming advice - originally write out your code step by step, and only combine steps once you know that the individual steps are working correctly.
Using your variable names, I think your code should look like this:
my $client = REST::Client->new();
# ...other code...
$client->GET($serverurl."serverinfo", $headers);
print $client->responseContent();
# And, only once you've established that
# $client->responseContent() returns what
# you expect, you can add this:
$idartinstance = decode_json($client->responseContent());
If the print() statement doesn't show you JSON, then update your question to add whatever is printed and we'll take a further look.

chrome.storage.sync save & load functions

I'm having trouble make a save & load function, here's what I'd like to do :
function save(key,val){
chrome.storage.sync.set({key:val}, function() {});
}
function load(key){
chrome.storage.sync.get([key], function(result) {return result});
}
Problem is, by doing that, my save function really create this in storage : {key: "{"key":"val"}"}
The save takes function literally takes "key", instead of taking it as a parameter.
Also, if I want load tu return my value, I need to do "result.key" instead of "result", but same problem, it takes it literally, it doesn't looks at key as a parameter.
And last problem is, if I place my return here, it doesn't work, and return nothing.
Could anyone help me fix it and understand what I did wrong please ?
ps : thanks for the asynchronous part, it helped a bit, I'll use a callback for the returned value, but it doesn't answer the other problems.

How to pass variable from module back to script?

I have noticed that variables inside a module function do not remain in scope after execution returns to the script. I came across Export-ModuleMember but that didn't seem to help, perhaps i'm using it wrong.
FunctionLibrary.psm1
Function AuthorizeAPI
{
# does a bunch of things to find $access_token
$access_token = "aerh137heuar7fhes732"
}
Write-Host $access_token
aerh137heuar7fhes732
Export-ModuleMember -Variable access_token -Function AuthorizeAPI
Main script
Import-Module FunctionLibrary
AuthorizeAPI # call to module function to get access_token
Write-Host $access_token
# nothing returns
I know as an alternative I could just dot source a separate script and that would allow me to get the access_token but I like the idea of using modules and having all my functions therein. Is this doable? Thanks SO!
As per #PetSerAl's comment, you can change the scope of your variable. Read up on scopes here. script scope did not work for me when running from console; global did.
$global:access_token = "aerh137heuar7fhes732"
Alternatively, you can return the value form the function it and store in a variable; no scope change needed.
Function
Function AuthorizeAPI
{
# does a bunch of things to find $access_token
$access_token = "aerh137heuar7fhes732"
return $access_token
}
Main Script
Import-Module FunctionLibrary
$this_access_token = AuthorizeAPI # call to module function to get access_token
Write-Host $this_access_token