Repository: getmoto/moto
Pull request #9058 (2025-07-14 07:30:13)

Core: rename InstanceTracker attribute
Renaming for clarity and to avoid colliding with subclass attribute names (e.g. `ec2:Reservation.instances`).

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/getmoto/moto/pull/9058?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 92.88%. Comparing base [(`cdbba08`)](https://app.codecov.io/gh/getmoto/moto/commit/cdbba089ed16cb39a0bd3b57140dbfc1ed850a62?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) to head [(`7dfd77d`)](https://app.codecov.io/gh/getmoto/moto/commit/7dfd77d7fa8c3b472052485339b24f162176a308?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #9058   +/-   ##
=======================================
  Coverage   92.88%   92.88%           
=======================================
  Files        1287     1287           
  Lines      113740   113740           
=======================================
+ Hits       105642   105645    +3     
+ Misses       8098     8095    -3     
```

| [Flag](https://app.codecov.io/gh/getmoto/moto/pull/9058/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | Coverage Δ | |
|---|---|---|
| [servertests](https://app.codecov.io/gh/getmoto/moto/pull/9058/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `28.58% <33.33%> (+<0.01%)` | :arrow_up: |
| [unittests](https://app.codecov.io/gh/getmoto/moto/pull/9058/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto) | `92.85% <100.00%> (+<0.01%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/getmoto/moto/pull/9058?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=getmoto).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>

Patch:
diff --git a/moto/core/base_backend.py b/moto/core/base_backend.py
index 75ca40e6f..095df2057 100644
--- a/moto/core/base_backend.py
+++ b/moto/core/base_backend.py
@@ -38,7 +38,7 @@ class InstanceTrackerMeta(type):
         service = cls.__module__.split(".")[1]
         if name not in model_data[service]:
             model_data[service][name] = cls
-        cls.instances: ClassVar[List["BaseModel"]] = []  # type: ignore
+        cls.instances_tracked: ClassVar[List["BaseModel"]] = []  # type: ignore
         return cls
 
 
diff --git a/moto/core/common_models.py b/moto/core/common_models.py
index 6fcdd35d5..973b2eaf2 100644
--- a/moto/core/common_models.py
+++ b/moto/core/common_models.py
@@ -11,7 +11,7 @@ class BaseModel(metaclass=InstanceTrackerMeta):
         **kwargs: Any,
     ) -> "BaseModel":
         instance = super(BaseModel, cls).__new__(cls)
-        cls.instances.append(instance)  # type: ignore[attr-defined]
+        cls.instances_tracked.append(instance)  # type: ignore[attr-defined]
         return instance
 
 
diff --git a/moto/core/model_instances.py b/moto/core/model_instances.py
index a73f333dd..26ae5ad3d 100644
--- a/moto/core/model_instances.py
+++ b/moto/core/model_instances.py
@@ -12,4 +12,4 @@ def reset_model_data() -> None:
     # Remove all references to the models stored
     for models in model_data.values():
         for model in models.values():
-            model.instances = []  # type: ignore[attr-defined]
+            model.instances_tracked = []  # type: ignore[attr-defined]
diff --git a/moto/moto_api/_internal/responses.py b/moto/moto_api/_internal/responses.py
index 00df8b134..0cc970be6 100644
--- a/moto/moto_api/_internal/responses.py
+++ b/moto/moto_api/_internal/responses.py
@@ -64,7 +64,7 @@ class MotoAPIResponse(BaseResponse):
             for name in sorted(models):
                 model = models[name]
                 results[service][name] = []
-                for instance in model.instances:  # type: ignore[attr-defined]
+                for instance in model.instances_tracked:  # type: ignore[attr-defined]
                     inst_result = {}
                     for attr in dir(instance):
                         if not attr.startswith("_"):
diff --git a/moto/s3/models.py b/moto/s3/models.py
index 2e5c10655..adbcd47d6 100644
--- a/moto/s3/models.py
+++ b/moto/s3/models.py
@@ -1767,9 +1767,9 @@ class S3Backend(BaseBackend, CloudWatchMetricProvider):
         #
         # Second, go through the list of instances
         # It may contain FakeKeys created earlier, which are no longer tracked
-        for mp in FakeMultipart.instances:  # type: ignore
+        for mp in FakeMultipart.instances_tracked:  # type: ignore
             mp.dispose()
-        for key in FakeKey.instances:  # type: ignore
+        for key in FakeKey.instances_tracked:  # type: ignore
             key.dispose()
         super().reset()
 
diff --git a/moto/ssm/resources/regions.json b/moto/ssm/resources/regions.json
index 2b9a87dce..89c0ddef1 100644
--- a/moto/ssm/resources/regions.json
+++ b/moto/ssm/resources/regions.json
@@ -3963,6 +3963,51 @@
                   "Value": "HTTPS"
                 }
               },
+              "fsx": {
+                "Value": "fsx",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "fsx-lustre": {
+                "Value": "fsx-lustre",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "fsx-ontap": {
+                "Value": "fsx-ontap",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "fsx-openzfs": {
+                "Value": "fsx-openzfs",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "fsx-windows": {
+                "Value": "fsx-windows",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "glue": {
                 "Value": "glue",
                 "endpoint": {
@@ -3999,6 +4044,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "kinesisanalytics": {
+                "Value": "kinesisanalytics",
+                "endpoint": {
+                  "Value": "kinesisanalytics.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "kms": {
                 "Value": "kms",
                 "endpoint": {
@@ -4179,6 +4233,24 @@
                   "Value": "HTTPS, HTTP"
                 }
               },
+              "sagemaker": {
+                "Value": "sagemaker",
+                "endpoint": {
+                  "Value": "api.sagemaker.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "scheduler": {
+                "Value": "scheduler",
+                "endpoint": {
+                  "Value": "scheduler.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "secretsmanager": {
                 "Value": "secretsmanager",
                 "endpoint": {
@@ -9693,6 +9765,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "workspaces-instances": {
+                "Value": "workspaces-instances",
+                "endpoint": {
+                  "Value": "workspaces-instances.ap-northeast-2.api.aws"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "xray": {
                 "Value": "xray",
                 "endpoint": {
@@ -24803,6 +24884,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "scheduler": {
+                "Value": "scheduler",
+                "endpoint": {
+                  "Value": "scheduler.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "secretsmanager": {
                 "Value": "secretsmanager",
                 "endpoint": {
@@ -25857,6 +25947,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "scheduler": {
+                "Value": "scheduler",
+                "endpoint": {
+                  "Value": "scheduler.ap-southeast-7.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "secretsmanager": {
                 "Value": "secretsmanager",
                 "endpoint": {
@@ -47198,6 +47297,12 @@
                   "Value": "HTTPS"
                 }
               },
+              "pcs": {
+                "Value": "pcs",
+                "endpoint": {
+                  "Value": "pcs.eu-west-2.amazonaws.com"
+                }
+              },
               "pi": {
                 "Value": "pi",
                 "endpoint": {
@@ -52122,6 +52227,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "elasticbeanstalk": {
+                "Value": "elasticbeanstalk",
+                "endpoint": {
+                  "Value": "elasticbeanstalk.me-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "elb": {
                 "Value": "elb",
                 "endpoint": {
@@ -55711,6 +55825,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "scheduler": {
+                "Value": "scheduler",
+                "endpoint": {
+                  "Value": "scheduler.mx-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "secretsmanager": {
                 "Value": "secretsmanager",
                 "endpoint": {
diff --git a/moto/ssm/resources/services.json b/moto/ssm/resources/services.json
index 90bc21fa0..9ade3904c 100644
--- a/moto/ssm/resources/services.json
+++ b/moto/ssm/resources/services.json
@@ -25231,6 +25231,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "me-central-1": {
+                "Value": "me-central-1",
+                "endpoint": {
+                  "Value": "elasticbeanstalk.me-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "me-south-1": {
                 "Value": "me-south-1",
                 "endpoint": {
@@ -29625,6 +29634,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -29960,6 +29978,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -30295,6 +30322,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -30630,6 +30666,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -30956,6 +31001,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "fsx.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -38874,6 +38928,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "kinesisanalytics.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -51102,6 +51165,12 @@
                   "Value": "pcs.eu-west-1.amazonaws.com"
                 }
               },
+              "eu-west-2": {
+                "Value": "eu-west-2",
+                "endpoint": {
+                  "Value": "pcs.eu-west-2.amazonaws.com"
+                }
+              },
               "us-east-1": {
                 "Value": "us-east-1",
                 "endpoint": {
@@ -59857,6 +59926,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "api.sagemaker.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -61390,6 +61468,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-east-2": {
+                "Value": "ap-east-2",
+                "endpoint": {
+                  "Value": "scheduler.ap-east-2.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ap-northeast-1": {
                 "Value": "ap-northeast-1",
                 "endpoint": {
@@ -61471,6 +61558,24 @@
                   "Value": "HTTPS"
                 }
               },
+              "ap-southeast-5": {
+                "Value": "ap-southeast-5",
+                "endpoint": {
+                  "Value": "scheduler.ap-southeast-5.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
+              "ap-southeast-7": {
+                "Value": "ap-southeast-7",
+                "endpoint": {
+                  "Value": "scheduler.ap-southeast-7.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "ca-central-1": {
                 "Value": "ca-central-1",
                 "endpoint": {
@@ -61606,6 +61711,15 @@
                   "Value": "HTTPS"
                 }
               },
+              "mx-central-1": {
+                "Value": "mx-central-1",
+                "endpoint": {
+                  "Value": "scheduler.mx-central-1.amazonaws.com"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              },
               "sa-east-1": {
                 "Value": "sa-east-1",
                 "endpoint": {
@@ -74819,6 +74933,23 @@
               }
             }
           },
+          "workspaces-instances": {
+            "Value": "workspaces-instances",
+            "longName": {
+              "Value": "Amazon Workspaces Instances"
+            },
+            "regions": {
+              "ap-northeast-2": {
+                "Value": "ap-northeast-2",
+                "endpoint": {
+                  "Value": "workspaces-instances.ap-northeast-2.api.aws"
+                },
+                "protocols": {
+                  "Value": "HTTPS"
+                }
+              }
+            }
+          },
           "workspaces-web": {
             "Value": "workspaces-web",
             "longName": {


Test patch:
diff --git a/tests/test_core/test_moto_api.py b/tests/test_core/test_moto_api.py
index 6b2b3c101..93f553956 100644
--- a/tests/test_core/test_moto_api.py
+++ b/tests/test_core/test_moto_api.py
@@ -97,7 +97,7 @@ def test_model_data_is_emptied_as_necessary() -> None:
     # No instances exist, because we have just reset it
     for classes_per_service in model_data.values():
         for _class in classes_per_service.values():
-            assert _class.instances == []  # type: ignore[attr-defined]
+            assert _class.instances_tracked == []  # type: ignore[attr-defined]
 
     # TODO: ensure that iam is not loaded, and IAM policies are not created
     # with mock_aws(load_static_data=False) ?
@@ -105,18 +105,18 @@ def test_model_data_is_emptied_as_necessary() -> None:
         # When just starting a mock, it is empty
         for classes_per_service in model_data.values():
             for _class in classes_per_service.values():
-                assert _class.instances == []  # type: ignore[attr-defined]
+                assert _class.instances_tracked == []  # type: ignore[attr-defined]
 
         # After creating a queue, some data will be present
         conn = boto3.client("sqs", region_name="us-west-1")
         conn.create_queue(QueueName="queue1")
 
-        assert len(model_data["sqs"]["Queue"].instances) == 1  # type: ignore[attr-defined]
+        assert len(model_data["sqs"]["Queue"].instances_tracked) == 1  # type: ignore[attr-defined]
 
     # But after the mock ends, it is empty again
     for classes_per_service in model_data.values():
         for _class in classes_per_service.values():
-            assert _class.instances == []  # type: ignore[attr-defined]
+            assert _class.instances_tracked == []  # type: ignore[attr-defined]
 
     # When we have multiple/nested mocks, the data should still be present after the first mock ends
     with mock_aws():
@@ -124,9 +124,9 @@ def test_model_data_is_emptied_as_necessary() -> None:
         conn.create_queue(QueueName="queue1")
         with mock_aws():
             # The data should still be here - instances should not reset if another mock is still active
-            assert len(model_data["sqs"]["Queue"].instances) == 1  # type: ignore[attr-defined]
+            assert len(model_data["sqs"]["Queue"].instances_tracked) == 1  # type: ignore[attr-defined]
         # The data should still be here - the inner mock has exited, but the outer mock is still active
-        assert len(model_data["sqs"]["Queue"].instances) == 1  # type: ignore[attr-defined]
+        assert len(model_data["sqs"]["Queue"].instances_tracked) == 1  # type: ignore[attr-defined]
 
 
 @mock_aws
@@ -138,10 +138,10 @@ class TestModelDataResetForClassDecorator(TestCase):
         # No data is present at the beginning
         for classes_per_service in model_data.values():
             for _class in classes_per_service.values():
-                assert _class.instances == []  # type: ignore[attr-defined]
+                assert _class.instances_tracked == []  # type: ignore[attr-defined]
 
         conn = boto3.client("sqs", region_name="us-west-1")
         conn.create_queue(QueueName="queue1")
 
     def test_should_find_bucket(self) -> None:
-        assert len(model_data["sqs"]["Queue"].instances) == 1  # type: ignore[attr-defined]
+        assert len(model_data["sqs"]["Queue"].instances_tracked) == 1  # type: ignore[attr-defined]