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

redundant processes for finding typelib-path and resolving it #358

Open
junkmd opened this issue Oct 2, 2022 · 1 comment
Open

redundant processes for finding typelib-path and resolving it #358

junkmd opened this issue Oct 2, 2022 · 1 comment

Comments

@junkmd
Copy link
Collaborator

junkmd commented Oct 2, 2022

Related to #327, I am refactoring tools.codegenerator and client._generate.

These modules include processing to turn passed relative paths into absolute paths and to find absolute paths to type libraries.

However, there are redundant processes as below.

  • There is a process to resolve relative paths in functions that are (possibly) passed absolute paths.
  • If the value returned by tlbparser.get_tlib_filename is None, there is a process that tries to get the absolute path of the type library by other methods.

if not os.path.isabs(full_filename):
# workaround Windows 7 bug in QueryPathOfRegTypeLib returning relative path
try:
dll = windll.LoadLibrary(full_filename)
full_filename = _get_module_filename(dll._handle)
del dll
except OSError:
return None
return full_filename

frame = sys._getframe(1)
_file_ = frame.f_globals.get("__file__", None)
pathname, is_abs = _resolve_filename(tlib_string, _file_ and os.path.dirname(_file_))
logger.debug("GetModule(%s), resolved: %s", pathname, is_abs)
tlib = _load_tlib(pathname) # don't register
if not is_abs:
# try to get path after loading, but this only works if already registered
pathname = tlbparser.get_tlib_filename(tlib)
if pathname is None:
logger.info("GetModule(%s): could not resolve to a filename", tlib)
pathname = tlib_string
# if above path torture resulted in an absolute path, then the file exists (at this point)!
assert not(os.path.isabs(pathname)) or os.path.exists(pathname)

def generate_code(self, items, filename):
tlib_mtime = None
if filename is not None:
# get full path to DLL first (os.stat can't work with relative DLL paths properly)
loaded_typelib = comtypes.typeinfo.LoadTypeLib(filename)
full_filename = tlbparser.get_tlib_filename(
loaded_typelib)
while full_filename and not os.path.exists(full_filename):
full_filename = os.path.split(full_filename)[0]
if full_filename and os.path.isfile(full_filename):
# get DLL timestamp at the moment of wrapper generation
tlib_mtime = os.stat(full_filename).st_mtime
if not full_filename.endswith(filename):
filename = full_filename

def _generate_typelib_path(self, filename):
# NOTE: the logic in this function appears completely different from that
# of the handling of tlib (given as a string) in GetModule. There, relative
# references are resolved wrt to the directory of the calling module. Here,
# resolution is with respect to current working directory -- later to be
# relativized to comtypes.gen.
if filename is not None:
if os.path.isabs(filename):
# absolute path
self.declarations.add("typelib_path", repr(filename))
elif not os.path.dirname(filename) and not os.path.isfile(filename):
# no directory given, and not in current directory.
self.declarations.add("typelib_path", repr(filename))
else:
# relative path; make relative to comtypes.gen.
path = self._make_relative_path(filename, comtypes.gen.__path__[0])
self.imports.add('os')
definition = "os.path.normpath(\n" \
" os.path.abspath(os.path.join(os.path.dirname(__file__),\n" \
" %r)))" % path
self.declarations.add("typelib_path", definition)
p = os.path.normpath(os.path.abspath(os.path.join(comtypes.gen.__path__[0],
path)))
assert os.path.isfile(p)

I would like to make sure that only client._generate does path-related processing for type libraries, and that tools.codegenerator only takes the path and generates code.

@junkmd
Copy link
Collaborator Author

junkmd commented Oct 3, 2022

@vasily-v-ryabov

I propose that it is no more defining typelib_path as relative path in _generate_typelib_path.
I would like to hear your opinion.
(because you have been committed 6c1788a and have added the following comments.)

def _generate_typelib_path(self, filename):
# NOTE: the logic in this function appears completely different from that
# of the handling of tlib (given as a string) in GetModule. There, relative
# references are resolved wrt to the directory of the calling module. Here,
# resolution is with respect to current working directory -- later to be
# relativized to comtypes.gen.

Rationale

Currently, there is still a conditional branch that makes the definition of typelib_path a path relative to the .../comtypes/gen directory, as shown below.

if filename is not None:
if os.path.isabs(filename):
# absolute path
self.declarations.add("typelib_path", repr(filename))
elif not os.path.dirname(filename) and not os.path.isfile(filename):
# no directory given, and not in current directory.
self.declarations.add("typelib_path", repr(filename))
else:
# relative path; make relative to comtypes.gen.
path = self._make_relative_path(filename, comtypes.gen.__path__[0])
self.imports.add('os')
definition = "os.path.normpath(\n" \
" os.path.abspath(os.path.join(os.path.dirname(__file__),\n" \
" %r)))" % path
self.declarations.add("typelib_path", definition)
p = os.path.normpath(os.path.abspath(os.path.join(comtypes.gen.__path__[0],
path)))
assert os.path.isfile(p)

Perhaps this is because there used to be a situation where tools.codegenerator was called as a script.

if __name__ == "__main__:" line is currently not in tools.codegenerator.

So currently it seems filename is already None or absolute path at the caller(client._generate.GetModule).

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

1 participant