Given some source files, load the full dependency graph. If an old_graph is passed in, it is used as the starting point and modified during graph loading. If a new_modules is passed in, any modules that are loaded are added to the list. This is an argument and not a return value
(
sources: list[BuildSource],
manager: BuildManager,
old_graph: Graph | None = None,
new_modules: list[State] | None = None,
)
| 4252 | |
| 4253 | |
| 4254 | def load_graph( |
| 4255 | sources: list[BuildSource], |
| 4256 | manager: BuildManager, |
| 4257 | old_graph: Graph | None = None, |
| 4258 | new_modules: list[State] | None = None, |
| 4259 | ) -> Graph: |
| 4260 | """Given some source files, load the full dependency graph. |
| 4261 | |
| 4262 | If an old_graph is passed in, it is used as the starting point and |
| 4263 | modified during graph loading. |
| 4264 | |
| 4265 | If a new_modules is passed in, any modules that are loaded are |
| 4266 | added to the list. This is an argument and not a return value |
| 4267 | so that the caller can access it even if load_graph fails. |
| 4268 | |
| 4269 | As this may need to parse files, this can raise CompileError in case |
| 4270 | there are syntax errors. |
| 4271 | """ |
| 4272 | |
| 4273 | graph: Graph = old_graph if old_graph is not None else {} |
| 4274 | |
| 4275 | # The deque is used to implement breadth-first traversal. |
| 4276 | # TODO: Consider whether to go depth-first instead. This may |
| 4277 | # affect the order in which we process files within import cycles. |
| 4278 | new = new_modules if new_modules is not None else [] |
| 4279 | entry_points: set[str] = set() |
| 4280 | # Seed the graph with the initial root sources. |
| 4281 | for bs in sources: |
| 4282 | try: |
| 4283 | st = State.new_state( |
| 4284 | id=bs.module, |
| 4285 | path=bs.path, |
| 4286 | source=bs.text, |
| 4287 | manager=manager, |
| 4288 | root_source=not bs.followed, |
| 4289 | ) |
| 4290 | except ModuleNotFound: |
| 4291 | continue |
| 4292 | if st.id in graph: |
| 4293 | manager.errors.set_file(st.xpath, st.id, manager.options) |
| 4294 | manager.error( |
| 4295 | None, |
| 4296 | f'Duplicate module named "{st.id}" (also at "{graph[st.id].xpath}")', |
| 4297 | blocker=True, |
| 4298 | ) |
| 4299 | resolution_note = f""" |
| 4300 | See {MODULE_RESOLUTION_URL} for more info |
| 4301 | Common resolutions include: |
| 4302 | a) using `--exclude` to avoid checking one of them, |
| 4303 | b) adding `__init__.py` somewhere, |
| 4304 | c) using `--explicit-package-bases` or adjusting `MYPYPATH` |
| 4305 | """ |
| 4306 | manager.note_multiline(None, resolution_note) |
| 4307 | manager.errors.raise_error() |
| 4308 | graph[st.id] = st |
| 4309 | new.append(st) |
| 4310 | entry_points.add(bs.module) |
| 4311 | manager.parse_all([state for state in new if state.needs_parse]) |
no test coverage detected
searching dependent graphs…