Skip to content

Python 3 imports: additional work on builtins, relative imports, importlib#8727

Merged
feerrenrut merged 12 commits into
nvaccess:masterfrom
josephsl:py3imports2
May 2, 2019
Merged

Python 3 imports: additional work on builtins, relative imports, importlib#8727
feerrenrut merged 12 commits into
nvaccess:masterfrom
josephsl:py3imports2

Conversation

@josephsl

@josephsl josephsl commented Sep 9, 2018

Copy link
Copy Markdown
Contributor

Link to issue number:

Fixes #8712
Fixes #8724
Fixes #8768

Summary of the issue:

More work on Python 3 imports, including relative imports and changing builtin to builtins, as well as using importlib to import modules at runtime.

Description of how this pull request fixes the issue:

Changes made:

  • Import builtin -> builtins (Python Console, language handler).
  • GUI and IAccessible objects: more relative imports (from . import ...).
  • Use importlib to import modules at runtime, including for IAccessible modules.

Testing performed:

Tested with Python 2.7 interpreter to make sure they are imported.

Known issues with pull request:

None

Change log entry:

None

* IAccessible: from winWord import ... -> from .winWord import ...
* GUI: from addonGui import ... -> from .addonGui import ...
Python Console and language handler imports __builtin__, which has been renamed to builtins in Python 3.
…ccessible support modules from the same folder. Re nvaccess#8712.

Python 3 wants a dot (.) when importing modules from the same folder. When using __import__ function, the level argument specifies search level (default is 0). Thus allow other IAccessible modules to be loaded by specifying level of 1 (relative import from the same folder).
@josephsl josephsl requested a review from feerrenrut September 9, 2018 05:20
@josephsl josephsl added the z Python 3 transition (archived) Python 3 transition label Sep 9, 2018
classString=classString[1:]
mod=__import__(modString,globals(),locals(),[])
# #8712: Python 3 wants a dot (.) when loading a module from the same folder via relative imports, and this is done via level argument.
mod=__import__(modString,globals(),locals(),[],1)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you call this with kwargs? Like:

mod=__import__(modString,globals=globals(),locals=locals(),level=1)

There is also the advice to use importlib.import_module, at least on python 2.

@josephsl

josephsl commented Sep 14, 2018 via email

Copy link
Copy Markdown
Contributor Author

@LeonarddeR

Copy link
Copy Markdown
Collaborator

@josephsl commented on 14 Sep 2018, 16:25 CEST:

Hi, importlib is new in Python 3 (if I read this correctly).

It is also there in Python 2.7.

Help on built-in function import in module builtin:

import(...)
import(name, globals={}, locals={}, fromlist=[], level=-1) -> module

Import a module. Because this function is meant for use by the Python

interpreter and not for general use, it is better to use
importlib.import_module() to programmatically import a module.

@josephsl

josephsl commented Sep 14, 2018 via email

Copy link
Copy Markdown
Contributor Author

@LeonarddeR

Copy link
Copy Markdown
Collaborator

I'd rather see this as part of this one. It creates unnecessary overhead if we have to change one line of code in this pr, and then change it again in the next.

See also #8768.

@josephsl josephsl changed the title Python 3 imports: additional work on builtins, relative imports Python 3 imports: additional work on builtins, relative imports, importlib Sep 20, 2018
…ly at runtime. Re nvaccess#8768.

Python 2.7 includes a base implementation of importlib which powers __import__ function, with Python 3 providing more features such as importers. Thus use importlib.import_module in app module handler and others, specifying appropriate package names in the process.
nvaccess#8712.

Because importlib.import_module complains about module names, spell the module name (NVDAObjects.IAccessible.mod).
@josephsl

Copy link
Copy Markdown
Contributor Author

Hi,

By the way, there is an unused "import Queue" in synthDrivers.espeak (no underscore), so I'm ignoring that one. People who will be working on transition should note that this import causes an exception, so should be removed then.

Thanks.

HRESULT no longer exists in ctypes.wintypes in Python 3. The new location is ctypes.HRESULT. Even in Python 2, ctypes.wintypes.HRESULT points to ctypes.HRESULT.
# Try querying the app module for the name of the app being hosted.
try:
# Python 2.x can't properly handle unicode module names, so convert them.
mod = __import__("appModules.%s" % appName.encode("mbcs"),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely going to fail on python 3

>>> "hello, %s" % "test".encode("mbcs")
"hello, b'test'"

str.format gives the same result.

It should be sufficient to check if not isinstance(appName, str) before encoding to mbcs.

@josephsl

josephsl commented Sep 24, 2018 via email

Copy link
Copy Markdown
Contributor Author

@LeonarddeR

LeonarddeR commented Sep 24, 2018 via email

Copy link
Copy Markdown
Collaborator

@josephsl

josephsl commented Sep 24, 2018 via email

Copy link
Copy Markdown
Contributor Author

…thon 2, no longer needed in Python 3.

Addressing review comment (reviewed by Leonard de Ruijter/Babbage): appName.encode('mbcs') will fail in Python 3, so do not do it unless one is using Python 2.
Note that this is an exception to the PR stream: nowhere in import_module call does encoding takes place.
@josephsl

Copy link
Copy Markdown
Contributor Author

Hi,

Addressed the import concern as of today's commit. As noted in the commit message, I'm making an exception, as nobody else calling import_module calls name.encode apart from app module handler.

Thanks.

Comment thread source/appModuleHandler.py Outdated
# Try querying the app module for the name of the app being hosted.
# Python 2.x can't properly handle unicode module names, so convert them.
# No longer the case in Python 3.
if sys.version.startswith("2"):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO its more elegant to do if isinstance(appName, bytes): bytes is a shortcut to str on python 2 and a separate type in python 3, so it will automatically apply to python 2 in this case. Alternatively, you can use sys.version_info.major

@josephsl

josephsl commented Sep 25, 2018 via email

Copy link
Copy Markdown
Contributor Author

@LeonarddeR

Copy link
Copy Markdown
Collaborator

Never mind, I was horribly wrong there. This place actually encodes (goes from unicode from bytes), my head was telling me that we had to decode (from bytes to unicode). So if it would have been isinstance, the right clause would be if not isinstance(appname, str):

@josephsl

josephsl commented Dec 7, 2018

Copy link
Copy Markdown
Contributor Author

Hi,

@feerrenrut, may I request a second look for this one? I'm interested in seeing if conflicts may arise when attempting to merge this pull request in the future.

Thanks.

@feerrenrut feerrenrut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. Given that it is tested against python 2.7, I think we should merge it in now. We don't have any intention of continuing to support Python 2.7 once we move over to 3 so I will add a task to the python 3 project board to remove any 2.7 specific code.

@LeonarddeR

Copy link
Copy Markdown
Collaborator

I agree.

@josephsl

Copy link
Copy Markdown
Contributor Author

Possible regression reported: multi-byte file name issue. Multiple possibilities, including Python 2.7.16, this PR, or something else.

Thanks.

josephsl added a commit that referenced this pull request May 31, 2019
josephsl added a commit that referenced this pull request May 31, 2019
josephsl added a commit that referenced this pull request May 31, 2019
michaelDCurran pushed a commit that referenced this pull request Jun 1, 2019
@LeonarddeR

Copy link
Copy Markdown
Collaborator

@josephsl: Could you please file this again against threshold?

@josephsl

josephsl commented Jun 4, 2019 via email

Copy link
Copy Markdown
Contributor Author

@josephsl josephsl deleted the py3imports2 branch July 19, 2020 22:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

4 participants