Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong value of __file__ #12

Closed
joonis opened this issue Mar 16, 2018 · 25 comments
Closed

Wrong value of __file__ #12

joonis opened this issue Mar 16, 2018 · 25 comments

Comments

@joonis
Copy link
Contributor

joonis commented Mar 16, 2018

The value of __ files __ seems to be hardcoded pointing to the original source file.

Is it possible to fix this?

@jondy
Copy link
Contributor

jondy commented Mar 16, 2018

I got it. The value of __file__ is filename in the build machine, not in the target machine. I'll try to fix it if it's possible.

@jondy
Copy link
Contributor

jondy commented Mar 16, 2018

Fix it by changing armor code to:

__pyarmor__(__name__, b'...').__file__ = __file__

@joonis
Copy link
Contributor Author

joonis commented Mar 16, 2018

But this will set it after the module was executed, isn't it?
So if a module wants to know its location and uses __file__, this fails.

Can't you modify __pyarmor__ to set it before executing the module?

__pyarmor__(__name__, __file__, b'...')

Alternatively when running Py_CompileString you could set the filename to <frozen [modname]>.
Here modname should be set to the passed __name__ param.

@jondy
Copy link
Contributor

jondy commented Mar 16, 2018

You're right. I prefer the first way, add extra parameter __file__

@jondy
Copy link
Contributor

jondy commented Mar 16, 2018

Fixed in v3.7.1, change armor code to

__pyarmor__(__name__, __file__, b'...')

@joonis
Copy link
Contributor Author

joonis commented Mar 16, 2018

Now __file__ is set to the correct path.

But a traceback still contains the wrong path names.

@jondy
Copy link
Contributor

jondy commented Mar 17, 2018

I got it. This is because only co_filename of module's code object has been changed, the co_filename of descendants still keep the original value.

@jondy
Copy link
Contributor

jondy commented Mar 17, 2018

For filename in traceback, I prefer the second way, that is, set filename to <frozen [modname]> when running Py_CompileString. Iterating all the descendants code object to set co_filename in runtime perhaps is not a good choice.

@joonis
Copy link
Contributor Author

joonis commented Mar 17, 2018

Yes, this should be the way to go.

@joonis
Copy link
Contributor Author

joonis commented Mar 17, 2018

Usually the frozen string is without square brackets. Just wanted to indicate the variable for the module name. So it should be:

<frozen module>
or
<frozen package.module>

@jondy
Copy link
Contributor

jondy commented Mar 17, 2018

The dotted module name can not be got directly when running Py_CompileString, the alternative way is to take --src as the root package. For example,

python pyarmor.py obfuscate --src=/home/jondy/workspace ...

# /home/jondy/workspace/foo.py -> <frozen foo>
# /home/jondy/workspace/libroot/pkg/foo.py -> <frozen libroot.pkg.foo>  even if "libroot" maybe is not a package

@joonis
Copy link
Contributor Author

joonis commented Mar 17, 2018

This shouldn't be a problem. But the square brackets [] should be removed.

@joonis
Copy link
Contributor Author

joonis commented Mar 17, 2018

And a package is referenced with <frozen [__init__]> at time, instead <frozen pkgname>.
The __name__ argument already contains the correct value and is passed to __pyarmor__(__name__, __file__, b'...')

@jondy
Copy link
Contributor

jondy commented Mar 17, 2018

Fixed in v3.7.3

$src/__init__.py will be referenced as <frozen __init__>

The sub package $src/pkgname/__init__.py will be referenced as <frozen pkgname.__init__>

@joonis
Copy link
Contributor Author

joonis commented Mar 17, 2018

Can't you use the passed __name__ argument for that?

@jondy
Copy link
Contributor

jondy commented Mar 17, 2018

There is no __name__ when obfuscating scripts in building machine, only the full path of source filename. The <frozen [modnam]> is made from source filename by myself, one solution is to take __init__.py as a special case

__pyarmor__(__name__, __file__, b'...') run in different time and in different machine. __file__ and __name__ is available here, but it need iterate all the code objects to set co_filename as I explains before. For now, only module code object's co_filename is set to __file__, the co_filename of other code objects (functions, methods) is same as build time.

@joonis
Copy link
Contributor Author

joonis commented Mar 17, 2018

Ok, I see. But couldn't you just strip the .__init__ part? It looks a bit ugly ;)

@jondy
Copy link
Contributor

jondy commented Mar 17, 2018

No problem :), you're terrific guy!

@joonis
Copy link
Contributor Author

joonis commented Mar 17, 2018

Hey, I want to get rid of Nuitka for my project. So it's all to my advantage ;)

@joonis
Copy link
Contributor Author

joonis commented Mar 18, 2018

With v3.7.4 I get <frozen src.pkgname> and <frozen pkgname.modname>.

But it should be: <frozen pkgname> and <frozen pkgname.modname>

@joonis
Copy link
Contributor Author

joonis commented Mar 18, 2018

If the src folder contains a file __init__.py, the src folder itself should be the base package. If there is no such file, the name of the src folder should be skipped.

Example with __init__.py:

  • src/
    • __init__.py <frozen src>
    • subpkg/
      • __init__.py <frozen src.subpkg>
      • submod.py <frozen src.subpkg.submod>
    • mod.py <frozen src.mod>

Example without __init__.py:

  • src/
    • subpkg/
      • __init__.py <frozen subpkg>
      • submod.py <frozen subpkg.submod>
    • mod.py <frozen mod>

@jondy
Copy link
Contributor

jondy commented Mar 18, 2018

Fixed in v3.7.5. There is another case

src/__init__.py
src/a                                            there is no __init__py
src/a/pkg/__init__.py
src/a/pkg/foo.py                           <frozen pkg.foo>

@joonis
Copy link
Contributor Author

joonis commented Mar 18, 2018

I propose that a missing __init__.py will always reset the package chain.

@joonis
Copy link
Contributor Author

joonis commented Mar 24, 2018

There is still an issue with co_filename of the module code object itself. Currently it is set to the same value as __file__. But it should be set to <frozen pkgname> as it is done for all code subobjects. Then it would be consistent over all code objects and gives a nice traceback. The real path remains accessible via __file__ attribute.

@jondy
Copy link
Contributor

jondy commented Mar 25, 2018

It's perfect. Fixed in v3.8.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants