Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use sourceless builder for builtin getattr #113340

Closed
wants to merge 16 commits into from

Conversation

pmeier
Copy link
Collaborator

@pmeier pmeier commented Nov 9, 2023

In TorchVision we use the following (simplified) dispatch mechanism:

import torch


def kernel1(tensor):
    return tensor + 2


def dispatcher1(input):
    kernel = get_kernel(dispatcher1, type(input))
    return kernel(input)


def kernel2(tensor):
    return tensor - 2


def dispatcher2(input):
    kernel = get_kernel(dispatcher2, type(input))
    return kernel(input)


# We actually use the function and type as keys, rather than their names.
# However, this currently not supported, but should be easy to add after
# https://github.com/pytorch/pytorch/pull/111196
REGISTRY = {
    "dispatcher1": {"Tensor": kernel1},
    "dispatcher2": {"Tensor": kernel2},
}


def get_kernel(dispatcher, input_type):
    dispatcher_registry = REGISTRY[dispatcher.__name__]
    for cls in input_type.__mro__:
        kernel = dispatcher_registry[cls.__name__]
        break
    return kernel

This can be compiled without graph breaks:

cfn = torch.compile(dispatcher1, fullgraph=True)
torch.testing.assert_close(int(cfn(torch.tensor(3))), 5)

cfn = torch.compile(dispatcher2, fullgraph=True)
torch.testing.assert_close(int(cfn(torch.tensor(3))), 1)

However, if we start chaining these calls, we hit some issues:

class Pipeline(torch.nn.Module):
    def forward(self, input):
        input = dispatcher1(input)
        input = dispatcher2(input)
        return input


cfn = torch.compile(Pipeline(), fullgraph=True)
torch.testing.assert_close(int(cfn(torch.tensor(3))), 3)
Can't access members of type(obj) for a generated custom object. Please use __class__ instead

The error message is not really helpful here. The following happens: when compiling dispatcher1, get_kernel gets inlined. That means when hitting dispatcher2, the type call no longer happens on an input with a source. Thus, in the first iteration we hit the top branch, while in the second we hit the bottom:

if py_type is not None and obj.source:
return VariableBuilder(tx, TypeSource(obj.source))(py_type)
if py_type is not None:
return ConstantVariable.create(py_type)

And the error message I posted above originates from the type being treated as constant. This PR replaces this with a SourcelessBuilder instead.

With that fix in place, we hit another pointing to input_type.__mro__

AssertionError: Consider SourcelessBuilder for ephemeral objects, usually objects created locally.

Fix is similar: instead of using a VariableBuilder here, we use a SourcelessBuilder in case we have no source:

else:
return VariableBuilder(tx, source)(member)

cc @voznesenskym @penguinwu @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @chenyang78 @aakhundov @kadeng @avikchaudhuri @gmagogsfm @zhxchen17 @tugsbayasgalan @angelayi @suo @ydwu4

Copy link

pytorch-bot bot commented Nov 9, 2023

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/113340

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit 8db8464 with merge base dadca7a (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@pmeier pmeier requested a review from lezcano November 9, 2023 14:17
@pmeier pmeier added the keep-going Don't stop on first failure, keep running tests until the end label Nov 9, 2023
Copy link
Collaborator

@peterbell10 peterbell10 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks reasonable as-is. There are probably some undesirable corner cases like dynamically created classes. However, one of the export test cases show that substituting type(A) with A.__class__ works today and I can't see why they should be treated differently.

torch/_dynamo/variables/builtin.py Outdated Show resolved Hide resolved
test/export/test_db.py Outdated Show resolved Hide resolved
@@ -1271,7 +1273,7 @@ def call_type(self, tx, obj: VariableTracker):
return VariableBuilder(tx, TypeSource(obj.source))(py_type)

if py_type is not None:
return ConstantVariable.create(py_type)
return SourcelessBuilder()(tx, py_type)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @yanboliang Is this alright? The issue torchvision was hitting was taht py_type = torch.Tensor coming from a sourceless tensor, it was wrongly being wrapped into a ConstantVariable rather than a TorchVariable.

Is this alright, or would you want us to be a bit less general here and just do this for torch.Tensor so that most paths still hit the UserError?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VariableTrackers produced by SourcelessBuilder are unguarded, what happens if there is a graph break after a type(obj) call if obj is generated internally (doesn't have a source)? I think it works well for constant and torch variables, we can't guarantee if they are other variables. But I don't expect a typecall returns too complicated data structure, so it should be fine IMO.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so Ed argues in #113390 that this is alright (that PR subsumes this one)

@pmeier
Copy link
Collaborator Author

pmeier commented Nov 10, 2023

Well, @ezyang beat me to it in #113390.

@pmeier pmeier marked this pull request as ready for review November 10, 2023 15:17
@albanD albanD added the triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module label Nov 10, 2023
Copy link
Collaborator

@lezcano lezcano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't Ed fixing this one?

Skylion007 pushed a commit to Skylion007/pytorch that referenced this pull request Nov 14, 2023
In TorchVision we use the following (simplified) dispatch mechanism:

```python
import torch

def kernel1(tensor):
    return tensor + 2

def dispatcher1(input):
    kernel = get_kernel(dispatcher1, type(input))
    return kernel(input)

def kernel2(tensor):
    return tensor - 2

def dispatcher2(input):
    kernel = get_kernel(dispatcher2, type(input))
    return kernel(input)

# We actually use the function and type as keys, rather than their names.
# However, this currently not supported, but should be easy to add after
# pytorch#111196
REGISTRY = {
    "dispatcher1": {"Tensor": kernel1},
    "dispatcher2": {"Tensor": kernel2},
}

def get_kernel(dispatcher, input_type):
    dispatcher_registry = REGISTRY[dispatcher.__name__]
    for cls in input_type.__mro__:
        kernel = dispatcher_registry[cls.__name__]
        break
    return kernel
```

This can be compiled without graph breaks:

```python
cfn = torch.compile(dispatcher1, fullgraph=True)
torch.testing.assert_close(int(cfn(torch.tensor(3))), 5)

cfn = torch.compile(dispatcher2, fullgraph=True)
torch.testing.assert_close(int(cfn(torch.tensor(3))), 1)
```

However, if we start chaining these calls, we hit some issues:

```python
class Pipeline(torch.nn.Module):
    def forward(self, input):
        input = dispatcher1(input)
        input = dispatcher2(input)
        return input

cfn = torch.compile(Pipeline(), fullgraph=True)
torch.testing.assert_close(int(cfn(torch.tensor(3))), 3)
```

```
Can't access members of type(obj) for a generated custom object. Please use __class__ instead
```

The error message is not really helpful here. The following happens: when compiling `dispatcher1`, `get_kernel` gets inlined. That means when hitting `dispatcher2`, the `type` call no longer happens on an input with a source. Thus, in the first iteration we hit the top branch, while in the second we hit the bottom:

https://github.com/pytorch/pytorch/blob/addb8e29cd842e1a290cb0b55662ee0423ab2498/torch/_dynamo/variables/builtin.py#L1264-L1268

And the error message I posted above originates from the type being treated as constant. This PR replaces this with a `SourcelessBuilder` instead.

With that fix in place, we hit another pointing to `input_type.__mro__`

```
AssertionError: Consider SourcelessBuilder for ephemeral objects, usually objects created locally.
```

Fix is similar: instead of using a `VariableBuilder` here, we use a `SourcelessBuilder` in case we have no `source`:

https://github.com/pytorch/pytorch/blob/addb8e29cd842e1a290cb0b55662ee0423ab2498/torch/_dynamo/variables/builtin.py#L1167-L1168

Pull Request resolved: pytorch#113340
Approved by: https://github.com/peterbell10, https://github.com/lezcano
@huydhn huydhn removed the keep-going Don't stop on first failure, keep running tests until the end label Nov 14, 2023
@huydhn
Copy link
Contributor

huydhn commented Nov 15, 2023

@pytorchbot revert -m 'Sorry for reverting your change, but the test is failing internally' -c ghfirst

2 test are failing

  • caffe2/test/dynamo:test_dynamo - test_export.py::DynamicShapesExportTests::test_access_class_method_from_user_class_type_fn_<function ExportTests_<lambda> at 0x7fe03d344b80>_dynamic_shapes
  • and caffe2/test/dynamo:test_dynamo - test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn_<function ExportTests_<lambda> at 0x7fe03d344b80>

I'm not quite sure what the parameterized lambdas are, but they both fail with no test found error:

Test appears to have passed but the binary exited with a non-zero exit code.
This usually means something has crashed after the test was done.
stdout:
============================= test session starts ==============================
platform linux -- Python 3.8.6, pytest-7.2.2, pluggy-0.13.1
rootdir: /data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/fbcode
plugins: hypothesis-6.70.1
collected 1171 items

============================ no tests ran in 7.25s =============================

stderr:
Traceback (most recent call last):
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/__run_lpar_main__.py", line 70, in <module>
    __invoke_main()
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/__run_lpar_main__.py", line 32, in __invoke_main
    run_as_main(module, main_function)
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/__par__/meta_only/bootstrap.py", line 88, in run_as_main
    oss_run_as_main(
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/__par__/bootstrap.py", line 58, in run_as_main
    runpy._run_module_as_main(main_module, alter_argv=False)
  File "/usr/local/fbcode/platform010/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/local/fbcode/platform010/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/testinfra/testpilot/integration/python/adapters/pytest.py", line 694, in <module>
    sys.exit(main())
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/testinfra/testpilot/integration/python/adapters/pytest.py", line 690, in main
    return PyTestTestPilotAdapter().run(sys.argv)
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/testinfra/testpilot/integration/python/adapters/base.py", line 322, in run
    return TestPilotCli(test_pilot_adapter=self).run(
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/testinfra/testpilot/integration/python/adapters/base.py", line 173, in run
    self._execute_tests(test_pilot_test_results, options=options)
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/testinfra/testpilot/integration/python/adapters/base.py", line 132, in _execute_tests
    test_results = self.test_pilot_adapter.execute_tests(
  File "/data/sandcastle/boxes/eden-trunk-hg-fbcode-fbsource/buck-out/v2/gen/fbcode/6081734815403318/caffe2/test/dynamo/__test_dynamo__/test_dynamo#link-tree/testinfra/testpilot/integration/python/adapters/pytest.py", line 678, in execute_tests
    assert len(results), "No test results returned!"
AssertionError: No test results returned!

exit_code:"Process terminated by the signal: 1"

@pytorchmergebot
Copy link
Collaborator

@pytorchbot successfully started a revert job. Check the current status here.
Questions? Feedback? Please reach out to the PyTorch DevX Team

@pytorchmergebot
Copy link
Collaborator

@pmeier your PR has been successfully reverted.

pytorchmergebot added a commit that referenced this pull request Nov 15, 2023
This reverts commit d64bc8f.

Reverted #113340 on behalf of https://github.com/huydhn due to Sorry for reverting your change, but the test is failing internally ([comment](#113340 (comment)))
@pmeier
Copy link
Collaborator Author

pmeier commented Nov 15, 2023

@huydhn Are you sure this is coming from this PR and not #113390? #113390 fixed some behavior with how types are handled by dynamo and in the process adapted the test

def test_access_class_method_from_user_class(self):

(the same test name as in your traceback above). Basically there was a check that an error was raised that was removed, since #113390 fixed the underlying issue.

My PR here also touches this test, but only cleans it up and does not change about the way dynamo deals with types.

That being said, if #113390 is reverted as well, we need to wait for it to be relanded before this PR is merged as well.

@pmeier
Copy link
Collaborator Author

pmeier commented Nov 15, 2023

Or maybe for whatever reason, the internal CI doesn't like lambdas in the parametrization? Not sure how this test came into being, but it seems like a "copy" from the test I linked above?

@pmeier
Copy link
Collaborator Author

pmeier commented Nov 15, 2023

Here is a diff to avoid having a lambda as part of the parametrization

diff --git a/test/dynamo/test_export.py b/test/dynamo/test_export.py
index 2653f08b4f8..e3cb30cc207 100644
--- a/test/dynamo/test_export.py
+++ b/test/dynamo/test_export.py
@@ -2851,8 +2851,13 @@ def forward(self, x):
         with self.assertRaisesRegex(RuntimeError, "Shape must be more than 4"):
             gm(torch.randn(3, 4, 5))
 
-    @common_utils.parametrize("type_fn", [type, lambda obj: obj.__class__])
-    def test_access_class_method_from_user_class(self, type_fn):
+    @common_utils.parametrize("type_access", ["builtin", "class"])
+    def test_access_class_method_from_user_class(self, type_access):
+        if type_access == "builtin":
+            type_fn = type
+        elif type_access == "class":
+            type_fn = lambda obj: obj.__class__
+
         class A:
             @classmethod
             def func(cls):

Not sure why the lambda could be a problem in the parametrization, but maybe worth a try?

@pmeier
Copy link
Collaborator Author

pmeier commented Nov 15, 2023

Tested my patch in #113340 (comment) with @NicolasHug and it passed internal checks.

The likely problem was that the lambda in the test name has a memory address in it and if test collection and execution are not happening in the same process, the test is not found.

@pytorchbot merge

@pytorchmergebot
Copy link
Collaborator

Merge started

Your change will be merged once all checks pass (ETA 0-4 Hours).

Learn more about merging in the wiki.

Questions? Feedback? Please reach out to the PyTorch DevX Team

Advanced Debugging
Check the merge workflow status
here

@malfet
Copy link
Contributor

malfet commented Nov 15, 2023

@pmeier to be frank, I would like to argue that having lambda address as part of the test name is bad UX
But I thought that @paramterize have a mechanism to assign a more repeatable/human understandable names to the test.
Also, I think even test rerun logic we use will not work correctly if test name changes with every materialization of the parameters.

@lezcano
Copy link
Collaborator

lezcano commented Nov 15, 2023

You can use subtest to give it a test a static name

@pmeier
Copy link
Collaborator Author

pmeier commented Nov 15, 2023

@malfet

I would like to argue that having lambda address as part of the test name is bad UX
But I thought that @paramterize have a mechanism to assign a more repeatable/human understandable names to the test.

Totally agree here. I made the same assumption as you regarding the test name. But now that I know that this is not the case, I pushed my patch from #113340 (comment) in 131e177 that gets rid of lambda parametrization, but rather just uses strings.

@lezcano

Subtest is only really valuable if you have a for loop inside your test, which is an antipattern to begin with. @parametrize is the way to go. While not as configurable as @pytest.mark.parametrize, it still has functionality to supply a callable to set the test name on a per parameter basis. But in the case at hand, this was more complicated than having a simple if / elif inside the test.

@pmeier
Copy link
Collaborator Author

pmeier commented Nov 16, 2023

@lezcano I was mistaken here. I thought you were talking about unittest.TestCase.subTest, when you probably actually talking about

correct? If so, you are right and I could have used that. Will send a cleanup PR.

pmeier added a commit that referenced this pull request Nov 16, 2023
#113340 was reverted initially due to a bad default parametrization name. The test looked like

```python
common_utils.parametrize(
    "type_fn",
    [
        type,
        lambda obj: obj.__class__,
    ],
)
def test_access_class_method_from_user_class(self, type_fn):
```

This is a valid parametrization, but results in these default test names:

```bash
❯ pytest test/dynamo/test_export.py -k test_access_class_method_from_user_class --co -q
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn_<class 'type'>
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn_<function ExportTests_<lambda> at 0x7f3be5de0c10>
```

Ignoring the whitespace in the test names, which can lead to other issues down the line, the problem in #113340 was that the lambda parameter included a memory address. IIUC, internally, the tests are not collected and run in the same process. Meaning, the address of the lambda and in turn the test name is no longer valid on the runner. This is fixed earlier in the stack by giving the parametrization an explicit name with `subtest`, but this PR is about preventing issues in the default case.

`pytest` solves this by simply using the name of the parameter plus its index as id in the test name:

```python
import pytest

class Foo:
    def __repr__(self):
        return str(id(self))

pytest.mark.parametrize(
    "bar",
    [
        pytest.param(type),
        pytest.param(lambda obj: obj.__class__),
        pytest.param(Foo()),
    ],
)
def test_foo(bar):
    pass
```

```
❯ pytest main.py --co -q
main.py::test_foo[type]
main.py::test_foo[<lambda>]
main.py::test_foo[bar2]
```

`pytest` has better defaults for `type` and `lambda` than we do, but is has a safe default for custom objects.

This PR aligns our default test name with `pytest`. Using the parametrization from above again, we now collect

```bash
❯ pytest test/dynamo/test_export.py -k test_access_class_method_from_user_class --co -q
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn0
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn1
```

which might not be as expressive at first glance, but at least prevents bugs.

[ghstack-poisoned]
pmeier added a commit that referenced this pull request Nov 16, 2023
#113340 was reverted initially due to a bad default parametrization name. The test looked like

```python
common_utils.parametrize(
    "type_fn",
    [
        type,
        lambda obj: obj.__class__,
    ],
)
def test_access_class_method_from_user_class(self, type_fn):
```

This is a valid parametrization, but results in these default test names:

```bash
❯ pytest test/dynamo/test_export.py -k test_access_class_method_from_user_class --co -q
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn_<class 'type'>
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn_<function ExportTests_<lambda> at 0x7f3be5de0c10>
```

Ignoring the whitespace in the test names, which can lead to other issues down the line, the problem in #113340 was that the lambda parameter included a memory address. IIUC, internally, the tests are not collected and run in the same process. Meaning, the address of the lambda and in turn the test name is no longer valid on the runner. This is fixed earlier in the stack by giving the parametrization an explicit name with `subtest`, but this PR is about preventing issues in the default case.

`pytest` solves this by simply using the name of the parameter plus its index as id in the test name:

```python
import pytest

class Foo:
    def __repr__(self):
        return str(id(self))

pytest.mark.parametrize(
    "bar",
    [
        pytest.param(type),
        pytest.param(lambda obj: obj.__class__),
        pytest.param(Foo()),
    ],
)
def test_foo(bar):
    pass
```

```
❯ pytest main.py --co -q
main.py::test_foo[type]
main.py::test_foo[<lambda>]
main.py::test_foo[bar2]
```

`pytest` has better defaults for `type` and `lambda` than we do, but is has a safe default for custom objects.

This PR aligns our default test name with `pytest`. Using the parametrization from above again, we now collect

```bash
❯ pytest test/dynamo/test_export.py -k test_access_class_method_from_user_class --co -q
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn0
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn1
```

which might not be as expressive at first glance, but at least prevents bugs.

[ghstack-poisoned]
pytorchmergebot pushed a commit that referenced this pull request Nov 16, 2023
Cleanup from #113340 (comment).

```
❯ pytest test/dynamo/test_export.py -k test_access_class_method_from_user_class --co -q
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_attr
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_builtin
```

Pull Request resolved: #113855
Approved by: https://github.com/lezcano, https://github.com/huydhn
pytorchmergebot pushed a commit that referenced this pull request Nov 16, 2023
#113340 was reverted initially due to a bad default parametrization name. The test looked like

```python
@common_utils.parametrize(
    "type_fn",
    [
        type,
        lambda obj: obj.__class__,
    ],
)
def test_access_class_method_from_user_class(self, type_fn):
```

This is a valid parametrization, but results in these default test names:

```bash
❯ pytest test/dynamo/test_export.py -k test_access_class_method_from_user_class --co -q
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn_<class 'type'>
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn_<function ExportTests_<lambda> at 0x7f3be5de0c10>
```

Ignoring the whitespace in the test names, which can lead to other issues down the line, the problem in #113340 was that the lambda parameter included a memory address. IIUC, internally, the tests are not collected and run in the same process. Meaning, the address of the lambda and in turn the test name is no longer valid on the runner. This is fixed earlier in the stack by giving the parametrization an explicit name with `subtest`, but this PR is about preventing issues in the default case.

`pytest` solves this by simply using the name of the parameter plus its index as id in the test name:

```python
import pytest

class Foo:
    def __repr__(self):
        return str(id(self))

@pytest.mark.parametrize(
    "bar",
    [
        pytest.param(type),
        pytest.param(lambda obj: obj.__class__),
        pytest.param(Foo()),
    ],
)
def test_foo(bar):
    pass
```

```
❯ pytest main.py --co -q
main.py::test_foo[type]
main.py::test_foo[<lambda>]
main.py::test_foo[bar2]
```

`pytest` has better defaults for `type` and `lambda` than we do, but is has a safe default for custom objects.

This PR aligns our default test name with `pytest`. Using the parametrization from above again, we now collect

```bash
❯ pytest test/dynamo/test_export.py -k test_access_class_method_from_user_class --co -q
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn0
test/dynamo/test_export.py::ExportTests::test_access_class_method_from_user_class_type_fn1
```

which might not be as expressive at first glance, but at least prevents bugs.
Pull Request resolved: #113856
Approved by: https://github.com/malfet, https://github.com/huydhn
ghstack dependencies: #113855
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ciflow/inductor ciflow/trunk Trigger trunk jobs on your pull request Merged module: dynamo open source release notes: dynamo Reverted topic: bug fixes topic category triaged This issue has been looked at a team member, and triaged and prioritized into an appropriate module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants