how to avoid dependency name-conflicts with global translation function _( ) in python? - localization

I'm trying to internationalize / translate a python app that is implemented as a wx.App(). I have things working for the most part -- I see translations in the right places. But there's a show-stopper bug: crashing at hard-to-predict times with errors like:
Traceback: ...
self.SetStatusText(_('text to be translated here'))
TypeError: 'numpy.ndarray' object is not callable
I suspect that one or more of the app's dependencies (there are quite a few) is clobbering the global translation function, _( ). One likely way would be doing so by using _ as the name of a dummy var when unpacking a tuple (which is fairly widespread practice). I made sure its not my app that is doing this, so I suspect its a dependency that is. Is there some way to "defend" against this, or otherwise deal with the issue?
I suspect this is a common situation, and so people have worked out how to handle it properly. Otherwise, I'll go with something like using a nonstandard name, such as _translate, instead of _. I think this would work, but be more verbose and a little harder to read., e.e.,

From the above I can not see what is going wrong.
Don't have issues with I18N in my wxPython application I do use matplotlib and numpy in it (not extensive).
Can you give the full traceback and/or a small runnable sample which shows the problem.
BTW, have you seen this page in the wxPython Phoenix doc which gives some other references at the end.
wxpython.org/Phoenix/docs/html/internationalization.html
Aha, if Translate works then you run into the issue of Python stealing "", you can workaround that by doing this:
Install a custom displayhook to keep Python from setting the global _ (underscore) to the value of the last evaluated expression. If we don't do this, our mapping of _ to gettext can get overwritten. This is useful/needed in interactive debugging with PyShell.
you do this by defining in your App module:
def _displayHook(obj):
"""Custom display hook to prevent Python stealing '_'."""
if obj is not None:
print repr(obj)
and then in your wx.App.OnInit method do:
# work around for Python stealing "_"
sys.displayhook = _displayHook

Related

Detect Whether Script Was Imported or Executed in Lua

In python, there is a common construction of the form if __name__ == "__main__": to detect whether the file was imported or executed directly. Usually, the only action taken in this conditional is to execute some "sensible, top level" function. This allows the same file to be used as a basic script and as a library module (and also as something an interactive user can import and use).
I was wondering if there is a clean and reliable way to do this in lua. I thought I could use the _REQUIREDNAME global variable, but it turns out that this was changed in Lua 5.1. Currently, the lua require passes arguments (in the variadic ...), so in principle, these can be examined. However, this is either not reliable, not clean, or probably both, because obviously when a script is executed arguments can be passed. So to do this safely, you would have to examine the arguments.
FWIW, require passes the module name as argument 1 (the string you called require on), and the path to the file it eventually found as argument 2. So there is a obviously some examination that can be done to try to detect this, which if not nearly as nice as if __name__ == "__main__": and can always be bypassed by a user by passing two suitably constructed arguments to the script. Not exactly a security threat, but I would hope there is a better solution.
I also experimented with another method, which I found very ugly but promising. This was to use debug.traceack(). If the script is executed directly, the traceback is very predictable, in fact, it only has 3 lines. I thought this might be it, although, like I said, an ugly hack for sure.
Do any more frequent lua users have advice? In effect, if I am writing module X, I want to either return X.main_func() in script mode or return X in import mode.
EDIT:
I took out an item which was actually incorrect (and makes my traceback solution workable). Additionally, the link provided in the comment by Egor Skriptunoff did provide another trick from the debug library which is even cleaner than using the traceback. Other than that, it seems that everyone ran into the same issues as me and the lua team has been disinterested in providing an official means to support this.
Based on the links provided by Egor, the current cleanest and safest way to do this seems to be as outlined here:
How to determine whether my code is running in a lua module?
which I repeat for ease of reference:
if pcall(debug.getlocal, 4, 1) then
print("in package")
else
print("in main script")
end
There is a whole thread about it here:
http://lua.2524044.n2.nabble.com/Modules-with-standalone-main-program-td7681497.html
Like I said, it seems this is a popular feature which is going to remain unsupported for the time being, but the debug.getlocal method seems to be what common lua developers have settled on for now.
A require() returning in package.loaded.
So simply check package.loaded for what you want.
Also as a good start for more experience in that methodic i suggest to write package.preload functions for require() stuff without manipulating the path.
A simple example for showing this...
# /usr/local/bin/lua -i
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> package.preload.mymod=function() return {dump=function(...)
>> local args={...}
>> local test,dump=pcall(assert,args[1])
>> if test then
>> for key,value in pairs(dump) do
>> io.write(string.format("%s=%s\n",key,value)):flush()
>> end
>> return true
>> else
>> return test,dump
>> end
>> end} end
> mymod=require('mymod')
> mymod.dump(package.loaded)
string=table: 0x56693590
mymod=table: 0x566aa890
utf8=table: 0x56694d80
package=table: 0x56691ed0
math=table: 0x56693cb0
table=table: 0x566920d0
_G=table: 0x56690730
debug=table: 0x566950e0
coroutine=table: 0x56692310
os=table: 0x56692e60
io=table: 0x566921b0
true

Nix Hydra throws errors on imports with <symbol>, where symbol is not <nixpkgs>

There is something that is not completely clear to me on hydra. The following jobset:
{ nixpkgs ? import <nixpkgs>
{ config.allowUnfree = true;
config.allowBroken = true;
}
, my_package ? path/to/package/default.nix ## working expr
}:
let
jobs = {
jobA = import ../path/to/jobA/default.nix {inherit my_package;};
};
in
jobs
with 2 build inputs:
ciSrc
nixpkgs
evaluates without errors, and then is built.
BUT, when I change the working expr to:
my_package ? import <my_package> ## problematic expr
and add a third build input:
my_package, Local Path, path/to/package/default.nix
I get the following error:
hydra-eval-jobs returned exit code 1:
error: undefined variable 'foo' at /nix/store/somehash-my_package/.../default.nix:61:11
(use '--show-trace' to show detailed location information)
Why do I get it? what am I missing here?
My NIX_PATH contains both <nixpkgs> that works, and <my_package>, which isn't. This is the only change i did that produces the error.
btw both versions are built by nix-build, as recommended by the hydra-manual
on the same machine and by the same user that the hydra uses.
can anyone please shed light on it?
I doubt that the undefined variable error message is directly caused by swapping the build inputs. It's more likely that the problem has been lurking for a while but never triggered, and swapping the inputs like this has caused it to surface. If that's the case, it's impossible to say what's causing the problem since you've stripped out all of the relevant information. To get better help in the future, I suggest that you post a minimal, complete example of code which encounters this problem. What you've posted is indeed minimal, but it's incomplete (the problem seems to be with package/default.nix, which you haven't included), and also doesn't look like code which encounters this problem (based on things like somehash, path/to/package, etc. I imagine that running this code would hit a syntax error first).
All we know is that a variable has been used without an accompanying binding. Your error message says that the variable is called foo, but I assume that's not the real name. Given this scant information, I would guess that the problem is in your package/default.nix file.
There are a few gotchas to keep in mind with paths in Nix:
Path values used by a derivation (like /tmp/project/foo.nix) will be copied to the Nix store and those values (e.g. /nix/store/...-foo.nix) will be used instead of the original path. This can break relative paths, e.g. if foo.nix references ./bar.nix, then the latter will resolve to /nix/store/bar.nix which doesn't exist. This can be managed by getting the directory added to the store, e.g. "${/tmp/project}/foo.nix".
String values, like "/tmp/project/foo.nix", do not cause things to be copied into the store.
It's easy for calculations to turn paths into strings, but hard to keep them as paths. One useful trick is to use + with a path as the first argument, e.g. /tmp + "/project" will produce the path /tmp/project. We can use this with "/.." to go up a level. As an extreme case, we can convert a string containing an absolute path to a path value by doing e.g. with { myString = "/foo/bar"; }; /tmp + "/..${myString}", which will give the path /tmp/../foo/bar which resolves to /foo/bar.
When a mutable local path gets inserted into the Nix store, it's only an immutable "snapshot". If the contents are changed later, it can be a little unpredictable whether the old, cached snapshot will be used or whether a new snapshot will be made. For this reason, it's important to look at the paths given in error messages, e.g. take a look at /nix/store/...-project/foo.nix rather than /tmp/foo.nix, since they may not contain the same thing.

How to call a function from a lua file of a c++/lua project on interactive terminal?

I'm reading some source codes of a project, which is a combination of c++ and lua, they are interwined through luabind.
There is a la.lua file, in which there is a function exec(arg). The lua file also uses functions/variables from other lua file, so it has statements as below in the beginning
module(..., package.seeall);
print("Loading "..debug.getinfo(1).source.."...")
require "client_config"
now I want to run la.exec() from interactive terminal(on linux), but I get errors like
attempt to index global 'lg' (a nil value)
if I want to import la.lua, I get
require "la"
Loading #./la.lua...
./la.lua:68: attempt to index global 'ld' (a nil value)
stack traceback:
./lg.lua:68: in main chunk
[C]: in function 'require'
stdin:1: in main chunk
[C]: ?
what can I do?
Well, what could be going wrong?
(Really general guesswork following, there's not much information in what you provided…)
One option is that you're missing dependencies because the files don't properly require all the things they depend on. (If A depends on & requires B and then C, and C depends on B but doesn't require it because it's implicitly loaded by A, directly loading C will fail.) So if you throw some hours at tracking down & fixing dependencies, things might suddenly work.
(However, depending on how the modules are written this may be impossible without a lot of restructuring. As an example, unless you set package.loaded["foo"] to foo's module table in foo before loading submdules, those submodules cannot require"foo". (Luckily, module does that, in newer code without module that's often forgotten – and then you'll get an endless loop (until the stack overflows) of foo loading other modules which load foo which loads other modules which …) Further, while "fixing" things so they load in the interpreter you might accidentally break the load order used by the program/library under normal operation which you won't notice until you try to run that one normally again. So it may simply cost too much time to fix dependencies. You might still be able to track down enough to construct a long lua -lfoo-lbar… one-off dependency list which might get things to run, but don't depend on it.)
Another option is that there are missing parts provided by C(++) modules. If these are written in the style of a Lua library (i.e. they have luaopen_FOO), they might load in the interpreter. (IIRC that's unlikely for C++ because it expects the main program to be C++-aware but lua is (usually? always?) plain C.) It's also possible that these modules don't work that way and need to be loaded in some other way. Yet another possibility might be that the main program pre-defines things in the Lua state(s) that it creates, which means that there is no module that you could load to get those things.
While there are some more variations on the above, these should be all of the general categories. If you suspect that your problem is the first one (merely missing dependency information), maybe throw some more time at this as you have a pretty good chance of getting it to work. If you suspect it's one of the latter two, there's a very high chance that you won't get it to work (at least not directly).
You might be able to side-step that problem by patching the program to open up a REPL and then do whatever it is you want to do from there. (The simplest way to do that is to call debug.debug(). It's really limited (no multiline, no implicit return, crappy error information), but if you need/want something better, something that behaves very much like the normal Lua REPL can be written in ~30 lines or so of Lua.)

Are Hack named functions fully first-class citizens?

HHVM 3.9 is not such a fan of ternary statements with named functions, even when passed through fun(), but ≥3.10 is totally fine with them. It seems as though this is one of few cases, however, because 3.9 does accept named functions returned from concrete functions, as well as accepting named functions passed into other functions (3v4l):
<?hh
echo ((() ==> fun('strlen'))())('Hello'); // 5
echo (($f, $v) ==> $f($v))(strlen, 'Hello'); // 5 + Notice: Use of undefined constant strlen - assumed 'strlen'
echo (true ? strlen : intval)('100'); // Fatal error: syntax error, unexpected '(', expecting ',' or ';' on line 3
What changed between 3.9 and 3.10? Are there any cases in HHVM ≥3.10 where named functions cannot be referenced and used this way?
First, when writing Hack, don't write your code at toplevel; the hh_client typechecker can't check anything at toplevel. And 3v4l doesn't run the typechecker at all, you need to run it locally.
That said, no, Hack doesn't really have first-class functions. Most of its behaviour here it inherited from PHP, which also doesn't have them. Back when I was working on the Hack team, we tossed around a lot of ideas for adding them to the language; it's an obvious addition and need. But the need was never quite strong enough such that we sat down and actually worked out the details for both the type system and runtime implications; in particular, how to work out some of the scoping issues that the current callables have. Anonymous functions fill out enough of the need, especially with Hack's short lambda syntax, that there was always something more pressing to deal with.
So Hack just has PHP's normal callable forms; fun is one of a few special functions which give information to the typechecker that the string you specified actually represents a function so the typechecker can do proper type analysis. But at the end of the day, fun just boils down to the usual PHP callable forms with a bit of extra magic in the typechecker.
As to the behaviour you indicate in your 3v4l link. Using strlen and intval like that would cause a type error in Hack, since those are syntactically constants but constants with those names don't exist since Hack doesn't have first-class functions -- or it would if the code weren't at toplevel and you were running the typechecker. As to why it causes a parse error in HHVM 3.9 (which masks the "invalid constant" errors you see in 3.10), I'm not 100% sure. Judging from this example which works in PHP7 and HHVM 3.10, but not PHP5 and HHVM 3.9, my guess it is a PHP7 feature that is backwards compatible and so is always enabled in HHVM.

How can I load a local file from embedded Rhino?

I'm using Rhino's context.evaluateString() to run some simple JavaScript from inside of Java. It's textbook right out of the Embedding Javascript guide:
String script = // simple logic
Context c = new ContextFactory().enterContext();
ScriptableObject scope = context.initStandardObjects();
Object o = context.evaluateString(scope, script, "myScript", 1, null);
ScriptableObject result = Context.jsToJava(o, ScriptableObject.class);
I'm not sure this is the current best-practice, because the main Rhino docs appear to be down, but it's working so far.
I'd like to be able to refer to a library in the working directory -- I see that Rhino shell supports load but I don't think this works in the embedding engine.
Is this possible? Is it documented anywhere? Ideally, I'd like to be able to just call something like load('other.js') and have it search directories I specify as a global property.
I have a sort-of answer that I don't really like, not least because it exposes what I'm pretty sure is a Rhino bug that drove me crazy for the last half hour:
eval("" + Packages.org.apache.commons.io.FileUtils.readFileToString(
new java.io.File("/the/local/root", "script.js");
));
{ That "" + ... is how I work around the bug -- if you eval() a Java String (such as is returned from the readFileToString call) without manually coercing it to a JavaScript native string, nothing appears to happen. The call just silently fails. }
This blindly reads an arbitrary file and evals it -- of course, this is what you do when you eval() from the Java side, so I don't worry about it too much.
Anyway, it's not elegant for a number of reasons, but it works. I'd love to hear a better answer!

Resources