Differing paths for lua script and app - c++

My problem is that I'm having trouble specifying paths for Lua to look in.
For example, in my script I have a require("someScript") line that works perfectly (it is able to use functions from someScript when the script is run standalone.
However, when I run my app, the script fails. I believe this is because Lua is looking in a location relative to the application rather than relative to the script.
Hardcoding the entire path down to the drive isn't an option since people can download the game wherever they like so the highest I can go is the root folder for the game.
We have XML files to load in information on objects. In them, when we specify the script the object uses, we only have to do something like Content/Core/Scripts/someScript.lua where Content is in the same directory as Debug and the app is located inside Debug. If I try putting that (the Content/Core...) in Lua's package.path I get errors when I try to run the script standalone.
I'm really stuck, and am not sure how to solve this. Any help is appreciated. Thanks.
P.S. When I print out the default package.path in the app I see syntax like ;.\?.lua
in a sequence like...
;.\?.lua;c:...(long file path)\Debug\?.lua; I assume the ; means the end of the path, but I have no idea what the .\?.lua means. Any Lua file in the directory?

You can customize the way require loads modules by putting your own loader into the package.loaders table. See here:
http://www.lua.org/manual/5.1/manual.html#pdf-package.loaders
If you want to be sure that things are nicely sandboxed, you'll probably want to remove all the default loaders and replace them with one that does exactly what you want and nothing more. (It will probably be somewhat similar to one of the existing ones, so you can use those as a guide.)

Related

Is there a way to apply SAS EG processes to new files?

I'm taking over a project from a coworker that involves several extensive SAS process flows. I have all the files with all the same names and a copy of the process flows they used. Since the file paths in their processes are direct references to their computer, normally I would just re-import the files with the same output names and run the process from there. In a few cases I would have to recreate a query builder as I'm using a few .sas7bdat files from another project.
However, there are quite a few files involved and I may end up having to pass this to another coworker in a few months, and since I can't get a good look at exactly what the import task is doing I'm concerned I may have some of the variables imported incorrectly. Is there an easy way to just change the file path the import or other task refers to?
Given the updates in comments, there's two possibilities I see.
If the paths you're changing are, or can be, relative to the location of the EGP, then you can right click on the Project->Properties->File References and check "Use paths relative to the project...", which means instead of storing a file in c:\my EGP folder\my code folder\code.sas it would store it as my code folder\code.sas. So then if the whole project moves to another computer (or just any other folder) then it automatically has the right path. This is mostly useful for code or similar things.
Otherwise, you're going to have to convert things to SAS code modules. There you can use macro variables to define the locations of things.

Methods for opening a specific file inside the project WITHOUT knowing what the working directory will be

I've had trouble with this issue across many languages, most recently with C++.
The Issue Exemplified
Let's say we're working with C++ and have the following file structure for a project:
("Project" main folder with three [modules, data, etc] subfolders)
Now say:
Our maincode.cpp is in the Project folder
moduleA.cpp is in modules folder
data.txt is in data folder
moduleA.cpp wants to read data.txt
So the way I'd currently do it would be to assume maincode.cpp gets compiled & executed inside the Project folder, and so hardcode the path data/data.txt in moduleA.cpp to do the reading (say I used fstream fs("data/data.txt") to do so).
But what if the code was, for some reason, executed inside etc folder?
Is there a way around this?
The Questions
Is this a valid question? Or am I missing something with the wd (working directory) concept fundamentals?
Are there any methods for working around absolute paths so as to solve this issue in C++?
Are there any universal methods for doing the same with any language?
If there are no reasonable methods, how would you approach this issue?
Please leave a comment if I missed any important details with the problem's illustration!
At some point the program has to make an assumption where the file(s) are. Either by getting it from user input or a relative path with the presumed filename. As already said in the comments, C++ recently got std::filesystem added in C++17 which can help you making cross-platform code that interacts with the hosts' filesystem.
That being said, every program, big or small, has to make certain assumptions at some point, deleting or moving certain files is problematic for any program in case the program requires them to be at a certain location under a certain name. This is not solvable other than presenting the user with an error message etc.
As #Hatted Rooster said, it's not generally solvable for some arbitrary file without making some assumptions, however there are frameworks that allow you to "store" some files in the resources embedded into the executable (or otherwise). Those frameworks would usually allow your to handle such files in a opaque way, without the need to rely on a current working dir or relative paths.
For example, see the Qt Resource System.
Your program can deduce the path from argv[0] in the main call, if you know that it is always relative to your executable or you use an absolute path like "C:\myProgram\data\data.txt".
The second approach works in every language.

When a file changes, I'd like to modify one or more different files

I've been scouring the web for hours looking for an approach to solving this problem, and I just can't find one. Hopefully someone can fast-track me. I'd like to cause the following behaviour:
When running ember s and a file of a certain extension is changed, I'd like to analyze the contents of that file and write to several other files in the same directory.
To give a specific example, let's assume I have a file called app/dashboard/dashboard.ember. dashboard.ember consists of 3 concatenated files: app/dashboard/controller.js, .../route.js, and .../template.hbs with a reasonable delimiter between the files. When dashboard.ember is saved, I'd like to call a function (inside an addon, I assume) that reads the file, splits it at the delimiter and writes the corresponding splitted files. ember-cli should then pick up the changed source (.js, .hbs, etc.) files that it knows how to handle, ignoring the .ember file.
I could write this as a standalone application, of course, but I feel like it should be integrated with the ember-cli build environment, but I can't figure out what concoction of hooks and tools I should use to achieve this.

finding my py modules in sub folders, from the main application working dir

this question might have been asked before, but I could not find it.
I am on a Linux box. I have py app that runs from a folder called /avt. (example)
I did not write this code, and it has about 12 modules that go with it. I was the lucky engineer to inherit this mess.
this app imports other modules that live under this dir /avt/bin
I want to be able find my modules in the /bin dir no matter where the current working dir is. sometimes the app changes dir to some other sub folders to perform some file I/O. Then should return, but seems like sometimes it does not make it back, because the code will error out with "no such file or directory" error. so I want to test for working dir each time before I do any file I/O to the /bin dir.
As an example, I want to create files in /bin, and then later open those files and read data from them. How can I test to make sure my current working dir is always /avt? and if it is not, then ch.dir to it? Note: it also has to be portable code meaning if must run on any directory structure on any Linux machine.
I tried this code, but it is not very clean I think. Python is not my main language. Is this coding proper and will it work for this? forgive me I don't know how to format it for this forum.
Avtfolder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if Avtfolder not in sys.path:
sys.path.insert(0, Avtfolder)
if Avtfolder.__contains__('/avt'):
modfilespath = Avtfolder + '/bin'
print 'bin dir is ' + modfilespath
else:
print 'directory lost...'
#write some code here that changes to the root /avt dir
I have a few notes.
First, I'm afraid you are mixing up two problems (or I couldn't tell from the question which one you're facing). These problems are:
I/O to files that can reside in different directories on different machines
Importing Python modules used by your app that can also be in slightly different locations.
The title of the question and some of the text suggests you're dealing with problem 2, whereas references to I/O and "no such file or directory" error point to problem 1.
Those are, however, separate problems and are treated separately. I won't be able to give the exact recipes on both, but here are some suggestions:
For problem 1: I don't think it's a good idea to do some I/O, create files, etc. in the folder where the user installs the Python libraries. It's a folder for Python modules, not data. Also, if the library is installed via setup.py, using pip or easy_install (if it isn't the case now, that can change in the future) then the program will probably habe insufficient permissions to write there, unless invoked as root. And that's right. Create files somewhere else.
As to "how to track the directory changes" part: I must confess I don't quite understand what you mean. Why do you even using the concept of "current directory"? In my mind you should just have some variable such as write_path, data_path, etc. and the code would be
data = open(os.path.join(data_path, 'data.foo'))
dump = open(os.path.join(write_path, 'dump.bar'), 'w')
etc.
Why do you even care where are your libraries located? I don't think it's right, I'd change that. This inspect.currentframe() stuff smells like you really need to rethink the design of the library.
Now, what the location of the libraries matters for is Problem 2. But again, the absolute path shouldn't matter (if it does, change that!). You only need all the modules to be inside one folder (or its subfolders). If they are in the same folder, you're good. import foo will just work. If some are in subfolders, those subfolders should have a file named __init__.py in them, and then they will be seen as modules by Python interpreter, so you'll be able to do from foo import bar, where foo is a subfolder with __init__.py and bar.py in it.
So, try to rewrite it so that you don't depend on where the .py files are. You really shouldn't need to use inspect there at all. On another note, don't use special methods like __contains__ directly unless you really need to. if '/avt' in Avtfolder will do the same.

PhysFS and Python embedding

I am writing a game engine and I'd like it to have Python scripting as well as support for mods using PhysFS.
My game data is stored something like this:
/
native
scripts
sprites
...
mods
mymodname
scripts
What I want is for the mod scripts to be able to 'import' the native scripts as if they were in the same directory. Is something like that possible using PhysFS?
You could create a symbolic link so that you can link those files/folders are in a higher directory, with PhysFS you can do:
PHYSFS_permitSymbolicLinks()
Then have PhysFS follow your symbolic links, hope this help :-)
EDIT: What I would do is symbolically link /mods/scripts to /native/mods-scripts so that /native/scripts can call mods-scripts (which actually points to /mods/scripts)
[I am the same person who asked the question.]
The solution I used eventually was to modify Python's sys.path when my program starts. This does not pollute the game's data directories with symbolic links and is overall much cleaner.