| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -57,6 +57,13 @@ def spam_with_globals_and_builtins(): | |||
| 57 | 57 | print(res) | |
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | + def spam_with_global_and_attr_same_name(): | ||
| 61 | + try: | ||
| 62 | + spam_minimal.spam_minimal | ||
| 63 | + except AttributeError: | ||
| 64 | + pass | ||
| 65 | + | ||
| 66 | + | ||
| 60 | 67 | def spam_full_args(a, b, /, c, d, *args, e, f, **kwargs): | |
| 61 | 68 | return (a, b, c, d, e, f, args, kwargs) | |
| 62 | 69 | ||
@@ -190,6 +197,7 @@ def ham_C_closure(z): | |||
| 190 | 197 | spam_minimal, | |
| 191 | 198 | spam_with_builtins, | |
| 192 | 199 | spam_with_globals_and_builtins, | |
| 200 | + spam_with_global_and_attr_same_name, | ||
| 193 | 201 | spam_full_args, | |
| 194 | 202 | spam_full_args_with_defaults, | |
| 195 | 203 | spam_args_attrs_and_builtins, | |
@@ -258,6 +266,7 @@ def ham_C_closure(z): | |||
| 258 | 266 | script_with_globals, | |
| 259 | 267 | spam_full_args_with_defaults, | |
| 260 | 268 | spam_with_globals_and_builtins, | |
| 269 | + spam_with_global_and_attr_same_name, | ||
| 261 | 270 | spam_full, | |
| 262 | 271 | ] | |
| 263 | 272 | ||
@@ -275,6 +284,7 @@ def ham_C_closure(z): | |||
| 275 | 284 | *PURE_SCRIPT_FUNCTIONS, | |
| 276 | 285 | script_with_globals, | |
| 277 | 286 | spam_with_globals_and_builtins, | |
| 287 | + spam_with_global_and_attr_same_name, | ||
| 278 | 288 | ] | |
| 279 | 289 | ||
| 280 | 290 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -701,6 +701,7 @@ def test_local_kinds(self): | |||
| 701 | 701 | 'checks': CO_FAST_LOCAL, | |
| 702 | 702 | 'res': CO_FAST_LOCAL, | |
| 703 | 703 | }, | |
| 704 | + defs.spam_with_global_and_attr_same_name: {}, | ||
| 704 | 705 | defs.spam_full_args: { | |
| 705 | 706 | 'a': POSONLY, | |
| 706 | 707 | 'b': POSONLY, | |
@@ -955,6 +956,10 @@ def new_var_counts(*, | |||
| 955 | 956 | purelocals=5, | |
| 956 | 957 | globalvars=6, | |
| 957 | 958 | ), | |
| 959 | + defs.spam_with_global_and_attr_same_name: new_var_counts( | ||
| 960 | + globalvars=2, | ||
| 961 | + attrs=1, | ||
| 962 | + ), | ||
| 958 | 963 | defs.spam_full_args: new_var_counts( | |
| 959 | 964 | posonly=2, | |
| 960 | 965 | posorkw=2, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1714,7 +1714,7 @@ static int | |||
| 1714 | 1714 | identify_unbound_names(PyThreadState *tstate, PyCodeObject *co, | |
| 1715 | 1715 | PyObject *globalnames, PyObject *attrnames, | |
| 1716 | 1716 | PyObject *globalsns, PyObject *builtinsns, | |
| 1717 | - struct co_unbound_counts *counts) | ||
| 1717 | + struct co_unbound_counts *counts, int *p_numdupes) | ||
| 1718 | 1718 | { | |
| 1719 | 1719 | // This function is inspired by inspect.getclosurevars(). | |
| 1720 | 1720 | // It would be nicer if we had something similar to co_localspluskinds, | |
@@ -1729,6 +1729,7 @@ identify_unbound_names(PyThreadState *tstate, PyCodeObject *co, | |||
| 1729 | 1729 | assert(builtinsns == NULL || PyDict_Check(builtinsns)); | |
| 1730 | 1730 | assert(counts == NULL || counts->total == 0); | |
| 1731 | 1731 | struct co_unbound_counts unbound = {0}; | |
| 1732 | + int numdupes = 0; | ||
| 1732 | 1733 | Py_ssize_t len = Py_SIZE(co); | |
| 1733 | 1734 | for (int i = 0; i < len; i += _PyInstruction_GetLength(co, i)) { | |
| 1734 | 1735 | _Py_CODEUNIT inst = _Py_GetBaseCodeUnit(co, i); | |
@@ -1747,6 +1748,12 @@ identify_unbound_names(PyThreadState *tstate, PyCodeObject *co, | |||
| 1747 | 1748 | if (PySet_Add(attrnames, name) < 0) { | |
| 1748 | 1749 | return -1; | |
| 1749 | 1750 | } | |
| 1751 | + if (PySet_Contains(globalnames, name)) { | ||
| 1752 | + if (_PyErr_Occurred(tstate)) { | ||
| 1753 | + return -1; | ||
| 1754 | + } | ||
| 1755 | + numdupes += 1; | ||
| 1756 | + } | ||
| 1750 | 1757 | } | |
| 1751 | 1758 | else if (inst.op.code == LOAD_GLOBAL) { | |
| 1752 | 1759 | int oparg = GET_OPARG(co, i, inst.op.arg); | |
@@ -1778,11 +1785,20 @@ identify_unbound_names(PyThreadState *tstate, PyCodeObject *co, | |||
| 1778 | 1785 | if (PySet_Add(globalnames, name) < 0) { | |
| 1779 | 1786 | return -1; | |
| 1780 | 1787 | } | |
| 1788 | + if (PySet_Contains(attrnames, name)) { | ||
| 1789 | + if (_PyErr_Occurred(tstate)) { | ||
| 1790 | + return -1; | ||
| 1791 | + } | ||
| 1792 | + numdupes += 1; | ||
| 1793 | + } | ||
| 1781 | 1794 | } | |
| 1782 | 1795 | } | |
| 1783 | 1796 | if (counts != NULL) { | |
| 1784 | 1797 | *counts = unbound; | |
| 1785 | 1798 | } | |
| 1799 | + if (p_numdupes != NULL) { | ||
| 1800 | + *p_numdupes = numdupes; | ||
| 1801 | + } | ||
| 1786 | 1802 | return 0; | |
| 1787 | 1803 | } | |
| 1788 | 1804 | ||
@@ -1932,20 +1948,24 @@ _PyCode_SetUnboundVarCounts(PyThreadState *tstate, | |||
| 1932 | 1948 | ||
| 1933 | 1949 | // Fill in unbound.globals and unbound.numattrs. | |
| 1934 | 1950 | struct co_unbound_counts unbound = {0}; | |
| 1951 | + int numdupes = 0; | ||
| 1935 | 1952 | Py_BEGIN_CRITICAL_SECTION(co); | |
| 1936 | 1953 | res = identify_unbound_names( | |
| 1937 | 1954 | tstate, co, globalnames, attrnames, globalsns, builtinsns, | |
| 1938 | - &unbound); | ||
| 1955 | + &unbound, &numdupes); | ||
| 1939 | 1956 | Py_END_CRITICAL_SECTION(); | |
| 1940 | 1957 | if (res < 0) { | |
| 1941 | 1958 | goto finally; | |
| 1942 | 1959 | } | |
| 1943 | 1960 | assert(unbound.numunknown == 0); | |
| 1944 | - assert(unbound.total <= counts->unbound.total); | ||
| 1961 | + assert(unbound.total - numdupes <= counts->unbound.total); | ||
| 1945 | 1962 | assert(counts->unbound.numunknown == counts->unbound.total); | |
| 1946 | - unbound.numunknown = counts->unbound.total - unbound.total; | ||
| 1947 | - unbound.total = counts->unbound.total; | ||
| 1963 | + // There may be a name that is both a global and an attr. | ||
| 1964 | + int totalunbound = counts->unbound.total + numdupes; | ||
| 1965 | + unbound.numunknown = totalunbound - unbound.total; | ||
| 1966 | + unbound.total = totalunbound; | ||
| 1948 | 1967 | counts->unbound = unbound; | |
| 1968 | + counts->total += numdupes; | ||
| 1949 | 1969 | res = 0; | |
| 1950 | 1970 | ||
| 1951 | 1971 | finally: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments