We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
isinstance test on dtype causes graph break
```
diff --git a/tests/test_repros.py b/tests/test_repros.py
index 4d590f7..3ede478 100755
--- a/tests/test_repros.py
+++ b/tests/test_repros.py
@@ -1246,3 +1246,11 @@ class ReproTests(torchdynamo.testing.TestCase):
 
         self.assertTrue(same(ref0, res0))
         self.assertTrue(same(ref1, res1))
+
+    def test_isinstance_dtype(self):
+        @torchdynamo.optimize("eager", nopython=True)
+        def fn(x):
+            isinstance(torch.bfloat16, torch.dtype)
+            return x
+
+        fn(torch.randn(3))
```

you get

```
Traceback (most recent call last):                                                                                               
  File "/raid/ezyang/torchdynamo/torchdynamo/convert_frame.py", line 278, in _convert_frame_assert                               
    code = transform_code_object(frame.f_code, transform)                                                                        
  File "/raid/ezyang/torchdynamo/torchdynamo/bytecode_transformation.py", line 338, in transform_code_object                     
    transformations(instructions, code_options)                                                                                  
  File "/raid/ezyang/torchdynamo/torchdynamo/convert_frame.py", line 254, in transform                                           
    tracer.run()                                                                                                                 
  File "/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py", line 306, in run                                              
    and self.step()                                                                                                              
  File "/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py", line 284, in step                                             
    getattr(self, inst.opname)(inst)                                                                                             
  File "/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py", line 145, in wrapper                                          
    return inner_fn(self, inst)                                                                                                  
  File "/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py", line 619, in CALL_FUNCTION                                    
    self.call_function(fn, args, {})                                                                                             
  File "/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py", line 220, in call_function                                    
    self.push(fn.call_function(self, args, kwargs))                                                                              
  File "/raid/ezyang/torchdynamo/torchdynamo/variables/builtin.py", line 220, in call_function                                   
    result = handler(tx, *args, **kwargs)                                                                                        
  File "/raid/ezyang/torchdynamo/torchdynamo/variables/builtin.py", line 354, in call_isinstance                                 
    arg_type = arg.python_type()                                                                                                 
  File "/raid/ezyang/torchdynamo/torchdynamo/variables/torch.py", line 67, in python_type                                        
    return super().python_type()                                                                                                 
  File "/raid/ezyang/torchdynamo/torchdynamo/variables/base.py", line 137, in python_type                                        
    raise NotImplementedError(f"{self} has no type")                                                                             
NotImplementedError: TorchVariable() has no type 
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `torchdynamo/allowed_functions.py`
Content:
```
1 import builtins
2 import collections
3 import copy
4 import functools
5 import inspect
6 import itertools
7 import math
8 import operator
9 import types
10 import warnings
11 from typing import Dict
12 from typing import Optional
13 from typing import Set
14 
15 import numpy
16 import torch
17 
18 from . import config
19 from .utils import is_safe_constant
20 
21 
22 def make_function_id_set(lazy_initializer):
23     """
24     Track a set of `id()`s of objects which are either allowed or not
25     allowed to go into the generated FX graph.  Use to test for torch.*,
26     numpy.*, builtins.*, etc.
27 
28     Support user modification to permit customization of what can be
29     added to the graph and what will cause a graph break.
30     """
31 
32     class FunctionIdSet:
33         function_ids: Optional[Set[int]] = None
34         function_names: Optional[Dict[int, str]] = None
35 
36         def __call__(self):
37             if self.function_ids is None:
38                 value = lazy_initializer()
39                 if isinstance(value, dict):
40                     self.function_ids = set(value.keys())
41                     self.function_names = value
42                 else:
43                     assert isinstance(value, set)
44                     self.function_ids = value
45             return self.function_ids
46 
47         def get_name(self, idx: int, default: str):
48             self()  # lazy init
49             return self.function_names.get(idx, default)
50 
51         def add(self, idx: int):
52             self()  # lazy init
53             self.function_ids.add(idx)
54 
55         def remove(self, idx: int):
56             if idx in self():
57                 self.function_ids.remove(idx)
58 
59         def __contains__(self, idx: int):
60             return idx in self()
61 
62     return FunctionIdSet()
63 
64 
65 @make_function_id_set
66 def _disallowed_function_ids():
67     remove = [
68         True,
69         False,
70         None,
71         collections.OrderedDict,
72         copy.copy,
73         copy.deepcopy,
74         inspect.signature,
75         math.__package__,
76         torch.__builtins__,
77         torch.autocast_decrement_nesting,
78         torch.autocast_increment_nesting,
79         torch.autograd.grad,
80         torch.clear_autocast_cache,
81         torch.cuda.current_device,
82         torch.distributions.constraints.is_dependent,
83         torch.distributions.normal.Normal,
84         torch.inference_mode,
85         torch.set_anomaly_enabled,
86         torch.set_autocast_cache_enabled,
87         torch.set_autocast_cpu_dtype,
88         torch.set_autocast_cpu_enabled,
89         torch.set_autocast_enabled,
90         torch.set_autocast_gpu_dtype,
91         torch.autograd.profiler.profile,
92         warnings.warn,
93     ]
94     return {id(x) for x in remove}
95 
96 
97 @make_function_id_set
98 def _allowed_function_ids():
99     """
100     Walk torch.* and get the ids of all the stuff in it
101     """
102     warnings.filterwarnings("ignore", category=UserWarning, module="torch.distributed")
103     torch_object_ids = dict()
104 
105     def _is_allowed_module_prefix(obj):
106         allowed_modules = ("torch", "math")
107         allowed_modules_dot = tuple([x + "." for x in allowed_modules])
108         module = inspect.getmodule(obj)
109         if module is None:
110             return False
111 
112         mod_name = module.__name__
113         return mod_name in allowed_modules or mod_name.startswith(allowed_modules_dot)
114 
115     def _find_torch_objects(module):
116         if any(
117             module.__name__.startswith(mod_name)
118             for mod_name in config.allowed_functions_module_string_ignorelist
119         ):
120             return
121         torch_object_ids[id(module)] = module.__name__
122         for name, obj in list(module.__dict__.items()):
123             if id(obj) not in torch_object_ids:
124                 if isinstance(obj, types.ModuleType):
125                     if obj.__name__.startswith("torch."):
126                         torch_object_ids[id(obj)] = f"{module.__name__}.{name}"
127                         _find_torch_objects(obj)
128                 elif _is_allowed_module_prefix(obj):
129                     torch_object_ids[id(obj)] = f"{module.__name__}.{name}"
130                 elif inspect.getmodule(obj) is None and not is_safe_constant(obj):
131                     torch_object_ids[id(obj)] = f"{module.__name__}.{name}"
132 
133     _find_torch_objects(torch)
134     _find_torch_objects(math)
135 
136     for idx in _disallowed_function_ids():
137         if idx in torch_object_ids:
138             del torch_object_ids[idx]
139 
140     return torch_object_ids
141 
142 
143 @make_function_id_set
144 def _builtin_function_ids():
145     rv = {
146         id(v): f"builtins.{k}"
147         for k, v in builtins.__dict__.items()
148         if not k.startswith("_") and callable(v)
149     }
150     rv.update(
151         {
152             id(v): f"operator.{k}"
153             for k, v in operator.__dict__.items()
154             if not k.startswith("_") and callable(v)
155         }
156     )
157     rv.update(
158         {id(v): f"functools.{v.__name__}" for v in (itertools.chain, itertools.islice)}
159     )
160     rv[id(functools.reduce)] = "functools.reduce"
161     return rv
162 
163 
164 @make_function_id_set
165 def _numpy_function_ids():
166     rv = dict()
167     for mod in (numpy, numpy.random):
168         rv.update(
169             {
170                 id(v): f"{mod.__name__}.{k}"
171                 for k, v in mod.__dict__.items()
172                 if callable(v)
173                 and (getattr(v, "__module__", None) or mod.__name__) == mod.__name__
174             }
175         )
176     return rv
177 
178 
179 def is_allowed(obj):
180     """Is this safe to trace like torch.add ?"""
181     # torch.ops is populated lazily so we don't necessarily have them in
182     # _allowed_function_ids.  Figure it out by testing the type instead
183     # in those cases
184     return id(obj) in _allowed_function_ids or isinstance(
185         obj,
186         (torch._ops.OpOverloadPacket, torch._ops.OpOverload, torch._ops._OpNamespace),
187     )
188 
189 
190 def torch_get_name(obj, default):
191     """Convert a torch.* funcion to a string"""
192     return _allowed_function_ids.get_name(id(obj), default)
193 
194 
195 def is_builtin(obj):
196     return id(obj) in _builtin_function_ids
197 
198 
199 def is_numpy(obj):
200     return isinstance(obj, numpy.ndarray) or id(obj) in _numpy_function_ids
201
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/torchdynamo/allowed_functions.py b/torchdynamo/allowed_functions.py
--- a/torchdynamo/allowed_functions.py
+++ b/torchdynamo/allowed_functions.py
@@ -91,6 +91,11 @@
         torch.autograd.profiler.profile,
         warnings.warn,
     ]
+    # extract all dtypes from torch
+    dtypes = [
+        obj for obj in torch.__dict__.values() if isinstance(obj, type(torch.float32))
+    ]
+    remove += dtypes
     return {id(x) for x in remove}

{"golden_diff": "diff --git a/torchdynamo/allowed_functions.py b/torchdynamo/allowed_functions.py\n--- a/torchdynamo/allowed_functions.py\n+++ b/torchdynamo/allowed_functions.py\n@@ -91,6 +91,11 @@\n         torch.autograd.profiler.profile,\n         warnings.warn,\n     ]\n+    # extract all dtypes from torch\n+    dtypes = [\n+        obj for obj in torch.__dict__.values() if isinstance(obj, type(torch.float32))\n+    ]\n+    remove += dtypes\n     return {id(x) for x in remove}\n", "issue": "isinstance test on dtype causes graph break\n```\r\ndiff --git a/tests/test_repros.py b/tests/test_repros.py\r\nindex 4d590f7..3ede478 100755\r\n--- a/tests/test_repros.py\r\n+++ b/tests/test_repros.py\r\n@@ -1246,3 +1246,11 @@ class ReproTests(torchdynamo.testing.TestCase):\r\n \r\n         self.assertTrue(same(ref0, res0))\r\n         self.assertTrue(same(ref1, res1))\r\n+\r\n+    def test_isinstance_dtype(self):\r\n+        @torchdynamo.optimize(\"eager\", nopython=True)\r\n+        def fn(x):\r\n+            isinstance(torch.bfloat16, torch.dtype)\r\n+            return x\r\n+\r\n+        fn(torch.randn(3))\r\n```\r\n\r\nyou get\r\n\r\n```\r\nTraceback (most recent call last):                                                                                               \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/convert_frame.py\", line 278, in _convert_frame_assert                               \r\n    code = transform_code_object(frame.f_code, transform)                                                                        \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/bytecode_transformation.py\", line 338, in transform_code_object                     \r\n    transformations(instructions, code_options)                                                                                  \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/convert_frame.py\", line 254, in transform                                           \r\n    tracer.run()                                                                                                                 \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py\", line 306, in run                                              \r\n    and self.step()                                                                                                              \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py\", line 284, in step                                             \r\n    getattr(self, inst.opname)(inst)                                                                                             \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py\", line 145, in wrapper                                          \r\n    return inner_fn(self, inst)                                                                                                  \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py\", line 619, in CALL_FUNCTION                                    \r\n    self.call_function(fn, args, {})                                                                                             \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/symbolic_convert.py\", line 220, in call_function                                    \r\n    self.push(fn.call_function(self, args, kwargs))                                                                              \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/variables/builtin.py\", line 220, in call_function                                   \r\n    result = handler(tx, *args, **kwargs)                                                                                        \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/variables/builtin.py\", line 354, in call_isinstance                                 \r\n    arg_type = arg.python_type()                                                                                                 \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/variables/torch.py\", line 67, in python_type                                        \r\n    return super().python_type()                                                                                                 \r\n  File \"/raid/ezyang/torchdynamo/torchdynamo/variables/base.py\", line 137, in python_type                                        \r\n    raise NotImplementedError(f\"{self} has no type\")                                                                             \r\nNotImplementedError: TorchVariable() has no type \r\n```\n", "before_files": [{"content": "import builtins\nimport collections\nimport copy\nimport functools\nimport inspect\nimport itertools\nimport math\nimport operator\nimport types\nimport warnings\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Set\n\nimport numpy\nimport torch\n\nfrom . import config\nfrom .utils import is_safe_constant\n\n\ndef make_function_id_set(lazy_initializer):\n    \"\"\"\n    Track a set of `id()`s of objects which are either allowed or not\n    allowed to go into the generated FX graph.  Use to test for torch.*,\n    numpy.*, builtins.*, etc.\n\n    Support user modification to permit customization of what can be\n    added to the graph and what will cause a graph break.\n    \"\"\"\n\n    class FunctionIdSet:\n        function_ids: Optional[Set[int]] = None\n        function_names: Optional[Dict[int, str]] = None\n\n        def __call__(self):\n            if self.function_ids is None:\n                value = lazy_initializer()\n                if isinstance(value, dict):\n                    self.function_ids = set(value.keys())\n                    self.function_names = value\n                else:\n                    assert isinstance(value, set)\n                    self.function_ids = value\n            return self.function_ids\n\n        def get_name(self, idx: int, default: str):\n            self()  # lazy init\n            return self.function_names.get(idx, default)\n\n        def add(self, idx: int):\n            self()  # lazy init\n            self.function_ids.add(idx)\n\n        def remove(self, idx: int):\n            if idx in self():\n                self.function_ids.remove(idx)\n\n        def __contains__(self, idx: int):\n            return idx in self()\n\n    return FunctionIdSet()\n\n\n@make_function_id_set\ndef _disallowed_function_ids():\n    remove = [\n        True,\n        False,\n        None,\n        collections.OrderedDict,\n        copy.copy,\n        copy.deepcopy,\n        inspect.signature,\n        math.__package__,\n        torch.__builtins__,\n        torch.autocast_decrement_nesting,\n        torch.autocast_increment_nesting,\n        torch.autograd.grad,\n        torch.clear_autocast_cache,\n        torch.cuda.current_device,\n        torch.distributions.constraints.is_dependent,\n        torch.distributions.normal.Normal,\n        torch.inference_mode,\n        torch.set_anomaly_enabled,\n        torch.set_autocast_cache_enabled,\n        torch.set_autocast_cpu_dtype,\n        torch.set_autocast_cpu_enabled,\n        torch.set_autocast_enabled,\n        torch.set_autocast_gpu_dtype,\n        torch.autograd.profiler.profile,\n        warnings.warn,\n    ]\n    return {id(x) for x in remove}\n\n\n@make_function_id_set\ndef _allowed_function_ids():\n    \"\"\"\n    Walk torch.* and get the ids of all the stuff in it\n    \"\"\"\n    warnings.filterwarnings(\"ignore\", category=UserWarning, module=\"torch.distributed\")\n    torch_object_ids = dict()\n\n    def _is_allowed_module_prefix(obj):\n        allowed_modules = (\"torch\", \"math\")\n        allowed_modules_dot = tuple([x + \".\" for x in allowed_modules])\n        module = inspect.getmodule(obj)\n        if module is None:\n            return False\n\n        mod_name = module.__name__\n        return mod_name in allowed_modules or mod_name.startswith(allowed_modules_dot)\n\n    def _find_torch_objects(module):\n        if any(\n            module.__name__.startswith(mod_name)\n            for mod_name in config.allowed_functions_module_string_ignorelist\n        ):\n            return\n        torch_object_ids[id(module)] = module.__name__\n        for name, obj in list(module.__dict__.items()):\n            if id(obj) not in torch_object_ids:\n                if isinstance(obj, types.ModuleType):\n                    if obj.__name__.startswith(\"torch.\"):\n                        torch_object_ids[id(obj)] = f\"{module.__name__}.{name}\"\n                        _find_torch_objects(obj)\n                elif _is_allowed_module_prefix(obj):\n                    torch_object_ids[id(obj)] = f\"{module.__name__}.{name}\"\n                elif inspect.getmodule(obj) is None and not is_safe_constant(obj):\n                    torch_object_ids[id(obj)] = f\"{module.__name__}.{name}\"\n\n    _find_torch_objects(torch)\n    _find_torch_objects(math)\n\n    for idx in _disallowed_function_ids():\n        if idx in torch_object_ids:\n            del torch_object_ids[idx]\n\n    return torch_object_ids\n\n\n@make_function_id_set\ndef _builtin_function_ids():\n    rv = {\n        id(v): f\"builtins.{k}\"\n        for k, v in builtins.__dict__.items()\n        if not k.startswith(\"_\") and callable(v)\n    }\n    rv.update(\n        {\n            id(v): f\"operator.{k}\"\n            for k, v in operator.__dict__.items()\n            if not k.startswith(\"_\") and callable(v)\n        }\n    )\n    rv.update(\n        {id(v): f\"functools.{v.__name__}\" for v in (itertools.chain, itertools.islice)}\n    )\n    rv[id(functools.reduce)] = \"functools.reduce\"\n    return rv\n\n\n@make_function_id_set\ndef _numpy_function_ids():\n    rv = dict()\n    for mod in (numpy, numpy.random):\n        rv.update(\n            {\n                id(v): f\"{mod.__name__}.{k}\"\n                for k, v in mod.__dict__.items()\n                if callable(v)\n                and (getattr(v, \"__module__\", None) or mod.__name__) == mod.__name__\n            }\n        )\n    return rv\n\n\ndef is_allowed(obj):\n    \"\"\"Is this safe to trace like torch.add ?\"\"\"\n    # torch.ops is populated lazily so we don't necessarily have them in\n    # _allowed_function_ids.  Figure it out by testing the type instead\n    # in those cases\n    return id(obj) in _allowed_function_ids or isinstance(\n        obj,\n        (torch._ops.OpOverloadPacket, torch._ops.OpOverload, torch._ops._OpNamespace),\n    )\n\n\ndef torch_get_name(obj, default):\n    \"\"\"Convert a torch.* funcion to a string\"\"\"\n    return _allowed_function_ids.get_name(id(obj), default)\n\n\ndef is_builtin(obj):\n    return id(obj) in _builtin_function_ids\n\n\ndef is_numpy(obj):\n    return isinstance(obj, numpy.ndarray) or id(obj) in _numpy_function_ids\n", "path": "torchdynamo/allowed_functions.py"}], "after_files": [{"content": "import builtins\nimport collections\nimport copy\nimport functools\nimport inspect\nimport itertools\nimport math\nimport operator\nimport types\nimport warnings\nfrom typing import Dict\nfrom typing import Optional\nfrom typing import Set\n\nimport numpy\nimport torch\n\nfrom . import config\nfrom .utils import is_safe_constant\n\n\ndef make_function_id_set(lazy_initializer):\n    \"\"\"\n    Track a set of `id()`s of objects which are either allowed or not\n    allowed to go into the generated FX graph.  Use to test for torch.*,\n    numpy.*, builtins.*, etc.\n\n    Support user modification to permit customization of what can be\n    added to the graph and what will cause a graph break.\n    \"\"\"\n\n    class FunctionIdSet:\n        function_ids: Optional[Set[int]] = None\n        function_names: Optional[Dict[int, str]] = None\n\n        def __call__(self):\n            if self.function_ids is None:\n                value = lazy_initializer()\n                if isinstance(value, dict):\n                    self.function_ids = set(value.keys())\n                    self.function_names = value\n                else:\n                    assert isinstance(value, set)\n                    self.function_ids = value\n            return self.function_ids\n\n        def get_name(self, idx: int, default: str):\n            self()  # lazy init\n            return self.function_names.get(idx, default)\n\n        def add(self, idx: int):\n            self()  # lazy init\n            self.function_ids.add(idx)\n\n        def remove(self, idx: int):\n            if idx in self():\n                self.function_ids.remove(idx)\n\n        def __contains__(self, idx: int):\n            return idx in self()\n\n    return FunctionIdSet()\n\n\n@make_function_id_set\ndef _disallowed_function_ids():\n    remove = [\n        True,\n        False,\n        None,\n        collections.OrderedDict,\n        copy.copy,\n        copy.deepcopy,\n        inspect.signature,\n        math.__package__,\n        torch.__builtins__,\n        torch.autocast_decrement_nesting,\n        torch.autocast_increment_nesting,\n        torch.autograd.grad,\n        torch.clear_autocast_cache,\n        torch.cuda.current_device,\n        torch.distributions.constraints.is_dependent,\n        torch.distributions.normal.Normal,\n        torch.inference_mode,\n        torch.set_anomaly_enabled,\n        torch.set_autocast_cache_enabled,\n        torch.set_autocast_cpu_dtype,\n        torch.set_autocast_cpu_enabled,\n        torch.set_autocast_enabled,\n        torch.set_autocast_gpu_dtype,\n        torch.autograd.profiler.profile,\n        warnings.warn,\n    ]\n    # extract all dtypes from torch\n    dtypes = [\n        obj for obj in torch.__dict__.values() if isinstance(obj, type(torch.float32))\n    ]\n    remove += dtypes\n    return {id(x) for x in remove}\n\n\n@make_function_id_set\ndef _allowed_function_ids():\n    \"\"\"\n    Walk torch.* and get the ids of all the stuff in it\n    \"\"\"\n    warnings.filterwarnings(\"ignore\", category=UserWarning, module=\"torch.distributed\")\n    torch_object_ids = dict()\n\n    def _is_allowed_module_prefix(obj):\n        allowed_modules = (\"torch\", \"math\")\n        allowed_modules_dot = tuple([x + \".\" for x in allowed_modules])\n        module = inspect.getmodule(obj)\n        if module is None:\n            return False\n\n        mod_name = module.__name__\n        return mod_name in allowed_modules or mod_name.startswith(allowed_modules_dot)\n\n    def _find_torch_objects(module):\n        if any(\n            module.__name__.startswith(mod_name)\n            for mod_name in config.allowed_functions_module_string_ignorelist\n        ):\n            return\n        torch_object_ids[id(module)] = module.__name__\n        for name, obj in list(module.__dict__.items()):\n            if id(obj) not in torch_object_ids:\n                if isinstance(obj, types.ModuleType):\n                    if obj.__name__.startswith(\"torch.\"):\n                        torch_object_ids[id(obj)] = f\"{module.__name__}.{name}\"\n                        _find_torch_objects(obj)\n                elif _is_allowed_module_prefix(obj):\n                    torch_object_ids[id(obj)] = f\"{module.__name__}.{name}\"\n                elif inspect.getmodule(obj) is None and not is_safe_constant(obj):\n                    torch_object_ids[id(obj)] = f\"{module.__name__}.{name}\"\n\n    _find_torch_objects(torch)\n    _find_torch_objects(math)\n\n    for idx in _disallowed_function_ids():\n        if idx in torch_object_ids:\n            del torch_object_ids[idx]\n\n    return torch_object_ids\n\n\n@make_function_id_set\ndef _builtin_function_ids():\n    rv = {\n        id(v): f\"builtins.{k}\"\n        for k, v in builtins.__dict__.items()\n        if not k.startswith(\"_\") and callable(v)\n    }\n    rv.update(\n        {\n            id(v): f\"operator.{k}\"\n            for k, v in operator.__dict__.items()\n            if not k.startswith(\"_\") and callable(v)\n        }\n    )\n    rv.update(\n        {id(v): f\"functools.{v.__name__}\" for v in (itertools.chain, itertools.islice)}\n    )\n    rv[id(functools.reduce)] = \"functools.reduce\"\n    return rv\n\n\n@make_function_id_set\ndef _numpy_function_ids():\n    rv = dict()\n    for mod in (numpy, numpy.random):\n        rv.update(\n            {\n                id(v): f\"{mod.__name__}.{k}\"\n                for k, v in mod.__dict__.items()\n                if callable(v)\n                and (getattr(v, \"__module__\", None) or mod.__name__) == mod.__name__\n            }\n        )\n    return rv\n\n\ndef is_allowed(obj):\n    \"\"\"Is this safe to trace like torch.add ?\"\"\"\n    # torch.ops is populated lazily so we don't necessarily have them in\n    # _allowed_function_ids.  Figure it out by testing the type instead\n    # in those cases\n    return id(obj) in _allowed_function_ids or isinstance(\n        obj,\n        (torch._ops.OpOverloadPacket, torch._ops.OpOverload, torch._ops._OpNamespace),\n    )\n\n\ndef torch_get_name(obj, default):\n    \"\"\"Convert a torch.* funcion to a string\"\"\"\n    return _allowed_function_ids.get_name(id(obj), default)\n\n\ndef is_builtin(obj):\n    return id(obj) in _builtin_function_ids\n\n\ndef is_numpy(obj):\n    return isinstance(obj, numpy.ndarray) or id(obj) in _numpy_function_ids\n", "path": "torchdynamo/allowed_functions.py"}]}