In discord.py I want to fix ERROR 'Unreachable code' - discord.py

My code is below.
But after returning, an error of'Unreachable code' occurs in holy.
I want to fix
I am Korean and I used a translator
act = [i for i in acts if isinstance(i, discord.CustomActivity)]
if act:
act = act[0]
else:
return
text = str(act.name)
if text:
holy = (f'상태메시지 : {text}')
else:
return
holy = ('상태메시지가 없습니다')```

In functions, return returns a value from the function and stops the function. So any code you write after typing return is unreachable. That's why you're getting this error. Your question doesn't contain much code, but as far as I can see, you can define the variable holy above return.

Related

Indesign Scripting: View array's actual content (strings) in ExtendScript console

I'm a beginning learner of InDesign scripting and would like to help myself with debugging, but my attempts seem to run into walls. Hope someone has some insights that will help me going forward.
I'm working on a little project that loops through some selected tables, puts the 3 tables into an array/variable (accomplished that) and then loops through the content of those tables to find a GREP match and store those in an array/variable (for further uses I won't get into now)
My main objective at this point: See exactly what text characters the .findGrep(); function is catching and display those in the Javascript Console of the ExtendScript Toolkit app.
So here's a bit of the journey up to this point, including codes tried and suggestions from others. (All of my attempted uses of these has failed...why I'm here now... and why this is long; my apologies)
Initial try.
var myTables = []; (in Data Browser this shows values of [object Table], [object Table], [object Table]
var myFinds = [];
var myTest = [];
var myCharacters = [];
app.findGrepPreferences = null;
app.findGrepPreferences.findWhat = "\"";
for (x = 0; x < myTables.length; x++) {
var myFinds = myTables[x].findGrep();
$.writeln(myFinds);
};
Notes on this code: Because not every table has the characters in the findWhat, sometimes in this loop myFinds has nothing, but when it does have something, it shows this in console [object Character],[object Character],[object Character]
So someone (firstHelp) gave me this: And it did not work... error thrown on .contents.toString(); *"undefined is not an object" which I thought, "ok, yes I see at times in the loop myFinds has nothing in it... more on this later"
var stringArray = [];
for( var n=0; n<myFinds.length; n++ ) {
stringArray[n] = myFinds[n].contents.toString();
};
$.writeln(myFinds.join("\r"));
Code revamp Gave up on the $.writeln(myFinds); within the loop and tried this in order to gather Grep finds in a variable/array that could be dealt with outside of loop.
for (x = 0; x < myTables.length; x++) {
$.writeln(myTables[x].cells.firstItem().texts[0].contents[0]);
myFinds.push(myTables[x].findGrep());
};
$.writeln(myFinds);
ExtendScript Toolkit console now showing this for myFinds:
*myFinds = [Array], [object Character], [object Character], [object...
+ (object symbol) 0 =
+ (object symbol) 1 = [object Character], [object Character], [object Character]
+ (object symbol) 2 =
+ (object symbol) _proto_ =*
*again tried the .contents.toString(); on the myFinds and still the same error, "undefined..." including targeting the array when it clearly had something in it.
**So then I get this tipoff...(but no helpful code to apply to what I already have)
"you are dealing with arrays of arrays mixed with texts.
So you have to check with each item of the result array if it is text
or another array of texts.
If it is an array loop that array."
And later this bit of code that is supposed to "flatten" my array... a = [].concat.apply([],a);
Replacing a with myFinds like this, myFinds = [].concat.apply([],myFinds); did absolutely nothing. The array and its contents showed no change in the console... and I have no idea how to loop through each item of this array within an array, find out if it's text or another array and then show its real contents to console.
Really...how many loops and if/thens etc do I need to run on one array to show its actual contents in the console? But I know I struggle with breaking down every little step I want, to its minute scripting granularity and so my ignorance regularly impedes me. I welcome any suggestions/tips to move me closer to my **main objective" as stated above. Thanks
Regarding the first help. The real reason why you get an error while accessing content property is that you don’t check the type of the object and presume it will be a Text object. As the findGrep may not find a Text occurrence, you actually get an empty array. And Array.prototype.contents doesn’t exist hence the error.
Then $.writeln is legacy of Adobe ExtendScript toolkit, the IDE for ExtendScript. This product is no longer de eloped and maintained by Adobe. You should consider using other logging techniques such as the Visual Studio ExtendScript plugin which will allow you to use breakpoints and everything you need.

Are breakpoints not working as they should in DartEditor?

I'm getting some unexpected behaviour in the most recent Dart editor (version 0.4.0_r18915).
I have this minimal command line app that was intended to either take a command line argument or not and print a hello -somenoe- message. The application works just fine. But the debuggins fails to stop at the breakpoints set inside each of the if statement bodies. (I wanted to look at the state of the application weather the options.arguments.isEmpty was true or false)
var person;
main(){
var options = new Options();
if(options.arguments.isEmpty){
person = "someone who forgot to pass a command-line argument";
} else {
person = options.arguments[0];
}
print("Hello, $person!");
}
Debugger will stop at breakpoints in other lines but not in:
person = "someone who forgot to pass a command-line argument";
or in:
person = options.arguments[0];
Yes, file a bug. My suspicion is that the debugger can only stop at what's called a "safepoint" and that the assignment of a constant to a variable doesn't create one. Adding some line above it, like
print("breakpoint");
should help if that's the case. But I've also seen other problems with breakpoints not firing.

How to print validation error outside of field constructor in Play framework 2

How can I show a validation error for a form field outside of a field constructor in Play framework 2? Here is what I tried:
#eventForm.("name").error.message
And I get this error:
value message is not a member of Option[play.api.data.FormError]
I'm confused because in the api docs it says message is a member of FormError. Also this works fine for global errors:
#eventForm.globalError.message
You can get a better grasp of it checking Form's sourcecode here
Form defines an apply method:
def apply(key: String): Field = Field(
this,
key,
constraints.get(key).getOrElse(Nil),
formats.get(key),
errors.collect { case e if e.key == key => e },
data.get(key))
That, as said in the doc, returns any field, even if it doesn't exist. And a Field has an errors member which returns a Seq[FormError]:
So, you could do something like that (for the Seq[FormError]):
eventForm("name").errors.foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm("name").error.map { error =>
<div>#error.message</div>
}
Or, you could use Form errors:
def errors(key: String): Seq[FormError] = errors.filter(_.key == key)
And get all errors of a given key. Like this (for the Seq[FormError]):
eventForm.errors("name").foreach { error =>
<div>#error.message</div>
}
Or (for the Option[FormError])
eventForm.error("name").map { error =>
<div>#error.message</div>
}
If you want more details, check the source code. It's well written and well commented.
Cheers!
EDIT:
As biesior commented: to show human readable pretty messages with different languages you have to check how play works I18N out here
To be thorough you're probably going to have to deal with I18N. It's not hard at all to get it all working.
After reading the documentation you may still find yourself a bit consufed. I'll give you a little push. Add a messages file to your conf folder and you can copy its content from here. That way you'll have more control over the default messages. Now, in your view, you should be able to do something like that:
eventForm.errors("name").foreach { error =>
<div>#Messages(error.message, error.args: _*)</div>
}
For instance, if error.message were error.invalid it would show the message previously defined in the conf/messages file Invalid value. args define some arguments that your error message may handle. For instance, if you were handling an error.min, an arg could be the minimum value required. In your message you just have to follow the {n} pattern, where n is the order of your argument.
Of course, you're able to define your own messages like that:
error.futureBirthday=Are you sure you're born in the future? Oowww hay, we got ourselves a time traveler!
And in your controller you could check your form like that (just one line of code to show you the feeling of it)
"year" -> number.verifying("error.furtureBirthday", number <= 2012) // 2012 being the current year
If you want to play around with languages, just follow the documentation.
Cheers, again!
As you said yourself, message is a member of FormError, but you have an Option[FormError]. You could use
eventForm("name").error.map(_.message).getOrElse("")
That gives you the message, if there is an error, and "" if there isn't.

How to debug Google Apps Script (aka where does Logger.log log to?)

In Google Sheets, you can add some scripting functionality. I'm adding something for the onEdit event, but I can't tell if it's working. As far as I can tell, you can't debug a live event from Google Sheets, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor.
So, I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor. When I run it from the Script Editor, I can view the logs by going to View->Logs...
I was hoping I'd be able to see the logs from when the event actually gets executed, but I can't figure it out.
How do I debug this stuff?
UPDATE:
As written in this answer,
Stackdriver Logging is the preferred method of logging now.
Use console.log() to log to Stackdriver.
Logger.log will either send you an email (eventually) of errors that have happened in your scripts, or, if you are running things from the Script Editor, you can view the log from the last run function by going to View->Logs (still in script editor). Again, that will only show you anything that was logged from the last function you ran from inside Script Editor.
The script I was trying to get working had to do with spreadsheets - I made a spreadsheet todo-checklist type thing that sorted items by priorities and such.
The only triggers I installed for that script were the onOpen and onEdit triggers. Debugging the onEdit trigger was the hardest one to figure out, because I kept thinking that if I set a breakpoint in my onEdit function, opened the spreadsheet, edited a cell, that my breakpoint would be triggered. This is not the case.
To simulate having edited a cell, I did end up having to do something in the actual spreadsheet though. All I did was make sure the cell that I wanted it to treat as "edited" was selected, then in Script Editor, I would go to Run->onEdit. Then my breakpoint would be hit.
However, I did have to stop using the event argument that gets passed into the onEdit function - you can't simulate that by doing Run->onEdit. Any info I needed from the spreadsheet, like which cell was selected, etc, I had to figure out manually.
Anyways, long answer, but I figured it out eventually.
EDIT:
If you want to see the todo checklist I made, you can check it out here
(yes, I know anybody can edit it - that's the point of sharing it!)
I was hoping it'd let you see the script as well. Since you can't see it there, here it is:
function onOpen() {
setCheckboxes();
};
function setCheckboxes() {
var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
var checklist_data_range = checklist.getDataRange();
var checklist_num_rows = checklist_data_range.getNumRows();
Logger.log("checklist num rows: " + checklist_num_rows);
var coredata = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
var coredata_data_range = coredata.getDataRange();
for(var i = 0 ; i < checklist_num_rows-1; i++) {
var split = checklist_data_range.getCell(i+2, 3).getValue().split(" || ");
var item_id = split[split.length - 1];
if(item_id != "") {
item_id = parseInt(item_id);
Logger.log("setting value at ("+(i+2)+",2) to " + coredata_data_range.getCell(item_id+1, 3).getValue());
checklist_data_range.getCell(i+2,2).setValue(coredata_data_range.getCell(item_id+1, 3).getValue());
}
}
}
function onEdit() {
Logger.log("TESTING TESTING ON EDIT");
var active_sheet = SpreadsheetApp.getActiveSheet();
if(active_sheet.getName() == "checklist") {
var active_range = SpreadsheetApp.getActiveSheet().getActiveRange();
Logger.log("active_range: " + active_range);
Logger.log("active range col: " + active_range.getColumn() + "active range row: " + active_range.getRow());
Logger.log("active_range.value: " + active_range.getCell(1, 1).getValue());
Logger.log("active_range. colidx: " + active_range.getColumnIndex());
if(active_range.getCell(1,1).getValue() == "?" || active_range.getCell(1,1).getValue() == "?") {
Logger.log("made it!");
var next_cell = active_sheet.getRange(active_range.getRow(), active_range.getColumn()+1, 1, 1).getCell(1,1);
var val = next_cell.getValue();
Logger.log("val: " + val);
var splits = val.split(" || ");
var item_id = splits[splits.length-1];
Logger.log("item_id: " + item_id);
var core_data = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("core_data");
var sheet_data_range = core_data.getDataRange();
var num_rows = sheet_data_range.getNumRows();
var sheet_values = sheet_data_range.getValues();
Logger.log("num_rows: " + num_rows);
for(var i = 0; i < num_rows; i++) {
Logger.log("sheet_values[" + (i) + "][" + (8) + "] = " + sheet_values[i][8]);
if(sheet_values[i][8] == item_id) {
Logger.log("found it! tyring to set it...");
sheet_data_range.getCell(i+1, 2+1).setValue(active_range.getCell(1,1).getValue());
}
}
}
}
setCheckboxes();
};
As far as I can tell, you can't debug a live event from google docs, so you have to do it from the debugger, which is pointless since the event argument passed to my onEdit() function will always be undefined if I run it from the Script Editor.
True - so define the event argument yourself for debugging. See How can I test a trigger function in GAS?
I was trying to use the Logger.log method to log some data whenever the onEdit function gets called, but this too seems like it only works when run from the Script Editor. When I run it from the Script Editor, I can view the logs by going to View->Logs...
True again, but there is help. Peter Hermann's BetterLog library will redirect all logs to a spreadsheet, enabling logging even from code that is not attached to an instance of the editor / debugger.
If you're coding in a spreadsheet-contained script, for example, you can add just this one line to the top of your script file, and all logs will go to a "Logs" sheet in the spreadsheet. No other code necessary, just use Logger.log() as you usually would:
Logger = BetterLog.useSpreadsheet();
2017 Update:
Stackdriver Logging is now available for Google Apps Script. From the menu bar in the script editor, goto:
View > Stackdriver Logging to view or stream the logs.
console.log() will write DEBUG level messages
Example onEdit() logging:
function onEdit (e) {
var debug_e = {
authMode: e.authMode,
range: e.range.getA1Notation(),
source: e.source.getId(),
user: e.user,
value: e.value,
oldValue: e. oldValue
}
console.log({message: 'onEdit() Event Object', eventObject: debug_e});
}
Then check the logs in the Stackdriver UI labeled onEdit() Event Object to see the output
I've gone through these posts and somehow ended up finding a simple answer, which I'm posting here for those how want short and sweet solutions:
Use console.log("Hello World") in your script.
Go to https://script.google.com/home/my and select your add-on.
Click on the ellipsis menu on Project Details, select Executions.
Click on the header of the latest execution and read the log.
A little hacky, but I created an array called "console", and anytime I wanted to output to console I pushed to the array. Then whenever I wanted to see the actual output, I just returned console instead of whatever I was returning before.
//return 'console' //uncomment to output console
return "actual output";
}
If you have the script editor open you will see the logs under View->Logs. If your script has an onedit trigger, make a change to the spreadsheet which should trigger the function with the script editor opened in a second tab. Then go to the script editor tab and open the log. You will see whatever your function passes to the logger.
Basically as long as the script editor is open, the event will write to the log and show it for you. It will not show if someone else is in the file elsewhere.
I am having the same problem, I found the below on the web somewhere....
Event handlers in Docs are a little tricky though. Because docs can handle multiple simultaneous edits by multiple users, the event handlers are handled server-side. The major issue with this structure is that when an event trigger script fails, it fails on the server. If you want to see the debug info you'll need to setup an explicit trigger under the triggers menu that emails you the debug info when the event fails or else it will fail silently.
It's far from elegant, but while debugging, I often log to the Logger, and then use getLog() to fetch its contents. Then, I either:
save the results to a variable (which can be inspected in the Google Scripts debugger—this works around cases where I can't set a breakpoint in some code, but I can set one in code that gets executed later)
write it to some temporary DOM element
display it in an alert
Essentially, it just becomes a JavaScript output issue.
It grossly lacks the functionality of modern console.log() implementations, but the Logger does still help debug Google Scripts.
Just as a notice. I made a test function for my spreadsheet. I use the variable google throws in the onEdit(e) function (I called it e). Then I made a test function like this:
function test(){
var testRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,7)
var testObject = {
range:testRange,
value:"someValue"
}
onEdit(testObject)
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(GetItemInfoSheetName).getRange(2,6).setValue(Logger.getLog())
}
Calling this test function makes all the code run as you had an event in the spreadsheet. I just put in the possision of the cell i edited whitch gave me an unexpected result, setting value as the value i put into the cell.
OBS! for more variables googles gives to the function go here: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events
Currently you are confined to the container bound nature of using scripts within docs. If you create a new script inside outside of docs then you will be able to export information to a google spreadsheet and use it like a logging tool.
For example in your first code block
function setCheckboxes() {
// Add your spreadsheet data
var errorSheet = SpreadsheetApp.openById('EnterSpreadSheetIDHere').getSheetByName('EnterSheetNameHere');
var cell = errorSheet.getRange('A1').offset(errorSheet.getLastRow(),0);
// existing code
var checklist = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("checklist");
var checklist_data_range = checklist.getDataRange();
var checklist_num_rows = checklist_data_range.getNumRows();
// existing logger
Logger.log("checklist num rows: " + checklist_num_rows);
//We can pass the information to the sheet using cell.setValue()
cell.setValue(new Date() + "Checklist num rows: " + checklist_num_rows);
When I'm working with GAS I have two monitors ( you can use two windows ) set up with one containing the GAS environment and the other containing the SS so I can write information to and log.
The dev console will log errors thrown by the app script, so you can just throw an error to get it logged as a normal console.log. It will stop execution, but it might still be useful for step by step debugging.
throw Error('hello world!');
will show up in the console similarly to console.log('hello world')
For Apps Script projects that are tied to a single Sheet (or doc) — in 2022 — there is no View menu like other answers suggest. Instead you need to look in the Executions menu on the left sidebar to see the executions of your onSelectionChange function (or any other function), from there you can click REFRESH until your console.log messages appear.
just debug your spreadsheet code like this:
...
throw whatAmI;
...
shows like this:

setAttribute, onClick and cross browser compatibility

I have read a number of posts about this but none with any solid answer. Here is my code:
// button creation
onew = document.createElement('input');
onew.setAttribute("type", "button");
onew.setAttribute("value", "hosts");
onew.onclick = function(){fnDisplay_Computers("'" + alines[i] + "'"); }; // ie
onew.setAttribute("onclick", "fnDisplay_Computers('" + alines[i] + "')"); // mozilla
odiv.appendChild(onew);
Now, the setAttribute() method (with the mozilla comment) works fine in mozilla but only if it comes AFTER the line above it. So in other words it seems to just default to whichever gets set last. The .onclick method (with the ie comment) does not work in either case, am I using it incorrectly?
Either way I can't find a way to make this work at all in IE, let alone in both. I did change the function call when using the .onclick method and it worked fine using just a simple call to an alert function which is why I believe my syntax is incorrect.
Long story short, I can't get the onclick parameter to work consistently between IE/Mozilla.
-- Nicholas
onew.setAttribute("type", "button");
Never use setAttribute on HTML documents. IE gets it badly wrong in many cases, and the DOM-HTML properties are shorter, faster and easier to read:
onew.type= 'button';
onew.onclick = function(){fnDisplay_Computers("'" + alines[i] + "'"); }; // ie
What is ‘alines’? Why are you converting it to a string and surrounding it with single quotes? It looks like you are trying to do something heinous involving evaluating code in a string (which is what you're doing below in the ‘onew.setAttribute’ version). Evaluating JavaScript code in strings is almost always the Wrong Thing; avoid it like the plague. In the above case, IE should do the same as Firefox: it shouldn't work.
If ‘alines[i]’ is a string, I guess what you're trying to do is make it remember that string by constructing a code string that will evaluate in JavaScript to the original string. But:
"'" + alines[i] + "'"
is insufficient. What happens if ‘alines[i]’ has an apostrophe in, or a backslash?
'O'Reilly'
you've got a syntax error and possible security hole. Now, you could do something laborious and annoying like:
"'" + alines[i].split('\\').join('\\\\').split("'").join("\\'") + "'"
to try to escape the string, but it's ugly and won't work for other datatypes. You could even ask JavaScript to do it for you:
uneval(alines[i])
But not all objects can even be converted to evaluatable JavaScript source strings; basically the entire approach is doomed to failure.
The normal thing to do if you just want to have the onclick callback call a function with a parameter is to write the code in the straightforward way:
onew.onclick= function() {
fnDisplay_Computers(alines[i]);
};
Generally this will work and is what you want. There is, however, a slight wrinkle which you may have hit here, which could be what is confusing you into considering the wacky approach with the strings.
Namely, if ‘i’ in this case is the variable of an enclosing ‘for’ loop, the reference to ‘alines[i]’ won't do what you think it does. The ‘i’ will be accessed by the callback function when the click happens — which is after the loop has finished. At this point the ‘i’ variable will be left with whatever value it had at the end of the loop, so ‘alines[i]’ will always be the last element of ‘alines’, regardless of which ‘onew’ was clicked.
(See eg. How to fix closure problem in ActionScript 3 (AS3) for some discussion of this. It's one of the biggest causes of confusion with closures in both JavaScript and Python, and should really be fixed at a language level some day.)
You can get around the loop problem by encapsulating the closure in its own function, like this:
function callbackWithArgs(f, args) {
return function() { f.apply(window, args); }
}
// ...
onew.onclick= callbackWithArgs(fnDisplay_Computers, [alines[i]]);
And in a later version of JavaScript, you'll be able to say simply:
onew.onclick= fnDisplay_Computers.bind(window, alines[i]);
If you would like to be able to use ‘Function.bind()’ in browsers today, you can get an implementation from the Prototype framework, or just use:
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner,
args.length===0? arguments : arguments.length===0? args :
args.concat(Array.prototype.slice.call(arguments, 0))
);
};
};
}
I usually use something like:
onew.onclick = new Function("fnDisplay_Computers('" + alines[i] + "')");
this should work both in IE e Firefox.
Use the addEventListener() function with "click" for the type argument for Mozilla-based browsers, and attachEvent() function with "onclick" as the sEvent argument for IE; I find it best to use a try/catch statement, for example:
try {
onew.attachEvent("onclick", //For IE
function(){fnDisplay_Computers("'" + alines[i] + "'"); });
}
catch(e) {
onew.addEventListener("click", //For Mozilla-based browsers
function(){fnDisplay_Computers("'" + alines[i] + "'"); },
false);
}
I think #3 protesteth too much. In a lot of situations I'm building a table dynamically and need to pass parameters to the callback function. It isn't a typesafe issue since my variable parm is an integer index to the table row in question. Here's code with both a variable and fixed parameter that seems to be cross-browser compliant:
for (i = 0; i < arrTableData.length; i++) {
eleTR = objTable.insertRow(i + 1);
cell = eleTR.insertCell(0);
cell.width = "21";
var myElement = document.createElement('img');
myElement.setAttribute('src', 'images/button_down.gif');
myElement.setAttribute('alt', 'Move item down');
myElement.onclick = new Function('moveItem(' + i + ',0)');
cell.appendChild(myElement);
}

Resources