import-checker: don't treat modules as relative one if not found
The previous patch ensures all module names are recorded in `imports`
as absolute names, so we no longer need to treat modules as ones
imported relatively from the target source if they appear to not be
from the stdlib.
import-checker: make imported_modules yield absolute dotted_name_of_path
This patch makes `imported_modules()` always yield absolute
`dotted_name_of_path()`-ed name by strict detection with
`fromlocal()`.
This change improves circular detection in some points:
- locally defined modules, of which name collides against one of
standard library, can be examined correctly
For example, circular import related to `commands` is overlooked
before this patch.
- names not useful for circular detection are ignored
Names below are also yielded before this patch:
- module names of standard library (= not locally defined one)
- non-module names (e.g. `node.nullid` of `from node import nullid`)
These redundant names decrease performance of circular detection.
For example, with files at
1ef96a3b8b89, average loops per file in
`checkmod()` is reduced from 165 to 109.
- `__init__` can be handled correctly in `checkmod()`
For example, current implementation has problems below:
- `from xxx import yyy` doesn't recognize `xxx.__init__` as imported
- `xxx.__init__` imported via `import xxx` is treated as `xxx`,
and circular detection is aborted, because `key` of such
module name is not `xxx` but `xxx.__init__`
- it is easy to enhance for `from . import xxx` style or so (in the
future)
Module name detection in `imported_modules()` can use information
in `ast.ImportFrom` fully.
It is assumed that all locally defined modules are correctly specified
to `import-checker.py` at once.
Strictly speaking, when `from foo.bar.baz import module1` imports
`foo.bar.baz.module1` module, current `imported_modules()` yields only
`foo.bar.baz.__init__`, even though also `foo.__init__` and
`foo.bar.__init__` should be yielded to detect circular import
exactly.
But this limitation is reasonable one for improvement in this patch,
because current `__init__` files in Mercurial seems to be implemented
carefully.
import-checker: add utility to examine what module is imported easily
`fromlocalfunc()` uses:
- `modulename` (of the target source) to compose absolute module
name imported relatively from it
It is assumed that `modulename` is an `dotted_name_of_path()`-ed
source file, which may have `.__init__` at the end of it.
This assumption makes composing `prefix` of relative name easy.
- `localmods` to examine whether there is a locally defined (=
Mercurial specific) module matching against the specified name
It is assumed that module names not existing in `localmods` are
ones of Python standard library.
subrepo: further replacement of try/except with 'next'
Burn StopIteration, Burn!
parsers: use 'next' instead of try/except
This get rid of another StopIteration abomination. The change in self.current
value is supposed to not matter as nobody should be calling '_advance' after
that (as per Matt wisdom).
dagparser: use 'next' instead of try/except for default value
"Ich liebe es wenn ein Plan funktioniert."
getlogrevs: rewrite a loop to get read of try/except
Get rid of the 'except StopIteration' abomination.
_makelogrevset: replace try/except with 'next' usage
More readable without the 'except StopIteration' abomination.
ignore: move readpatternfile to match.py
In preparation for adding 'include:' rule support to match.py, let's move the
pattern file reader function to match.py
ignore: rename readignorefile to readpatternfile
A future commit will move the readignorefile logic into match.py so it can be
used from general match rules. Let's rename the function to represent this new
behavior.