Repository: serge-sans-paille/beniget

Issue:
AssertionError in the __debug__ sanity checks when parsing idlelib.config
It can be reproduced as follows, but I don't have a minimal reproducer at the moment.

```
% curl --silent https://raw.githubusercontent.com/python/cpython/3.12/Lib/idlelib/config.py > test.py
% python3 -m beniget test.py 
W: unbound identifier 'line' at test.py:885:8
W: unbound identifier 'crc' at test.py:886:50
[...]
  File "beniget/beniget.py", line 616, in visit_Module
    assert nb_defs == nb_heads + nb_bltns - nb_overloaded_bltns
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError
```


Discussion:

Patch:
diff --git a/beniget/beniget.py b/beniget/beniget.py
index 4faa64d..fe38b13 100644
--- a/beniget/beniget.py
+++ b/beniget/beniget.py
@@ -665,6 +665,14 @@ class DefUseChains(ast.NodeVisitor):
     def extend_global(self, name, dnode_or_dnodes):
         if self._deadcode:
             return
+        # `name` *should* be in self._definitions[0] because we extend the
+        # globals. Yet the original code maybe faulty and we need to cope with
+        # it.
+        if name not in self._definitions[0]:
+            if isinstance(dnode_or_dnodes, Def):
+                self.locals[self.module].append(dnode_or_dnodes)
+            else:
+                self.locals[self.module].extend(dnode_or_dnodes)
         DefUseChains.add_to_definition(self._definitions[0], name,
                                        dnode_or_dnodes)
 


Test patch:
diff --git a/tests/test_chains.py b/tests/test_chains.py
index 1e9bdaa..d2fa72c 100644
--- a/tests/test_chains.py
+++ b/tests/test_chains.py
@@ -111,6 +111,9 @@ class TestDefUseChains(TestCase):
         self.checkChains(code, ['a -> (a -> ())',
                                 'foo -> ()'])
 
+    def test_augassign_undefined_global(self):
+        code = "def foo():\n def bar():\n  global x\n  x+=1; x"
+        self.checkChains(code, ['foo -> ()', 'x -> (x -> ())'], strict=False)
 
     def test_expanded_augassign(self):
         code = "a = 1; a = a + 2"