• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

localstack / localstack / 22334798432

23 Feb 2026 06:42PM UTC coverage: 86.956% (-0.02%) from 86.973%
22334798432

push

github

web-flow
S3: regenerate test snapshots & parity fixes (#13824)

69831 of 80306 relevant lines covered (86.96%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.25
/localstack-core/localstack/utils/tagging.py
1
from dataclasses import dataclass, field
1✔
2
from warnings import deprecated
1✔
3

4

5
@deprecated("`TaggingService` is deprecated. Please use the `RGTAPlugin`/`Tags` system.")
1✔
6
class TaggingService:
1✔
7
    key_field: str
1✔
8
    value_field: str
1✔
9

10
    tags: dict[str, dict[str, str]]
1✔
11

12
    def __init__(self, key_field: str = "Key", value_field: str = "Value"):
1✔
13
        """
14
        :param key_field: the field name representing the tag key as used by botocore specs
15
        :param value_field: the field name representing the tag value as used by botocore specs
16
        """
17
        self.key_field = key_field
1✔
18
        self.value_field = value_field
1✔
19

20
        self.tags = {}
1✔
21

22
    def list_tags_for_resource(self, arn: str, root_name: str | None = None):
1✔
23
        root_name = root_name or "Tags"
1✔
24

25
        result = []
1✔
26
        if arn in self.tags:
1✔
27
            for k, v in self.tags[arn].items():
1✔
28
                result.append({self.key_field: k, self.value_field: v})
1✔
29
        return {root_name: result}
1✔
30

31
    def tag_resource(self, arn: str, tags: list[dict[str, str]]):
1✔
32
        if not tags:
1✔
33
            return
1✔
34
        if arn not in self.tags:
1✔
35
            self.tags[arn] = {}
1✔
36
        for t in tags:
1✔
37
            self.tags[arn][t[self.key_field]] = t[self.value_field]
1✔
38

39
    def untag_resource(self, arn: str, tag_names: list[str]):
1✔
40
        tags = self.tags.get(arn, {})
1✔
41
        for name in tag_names:
1✔
42
            tags.pop(name, None)
1✔
43

44
    def del_resource(self, arn: str):
1✔
45
        if arn in self.tags:
1✔
46
            del self.tags[arn]
1✔
47

48
    def __delitem__(self, arn: str):
1✔
49
        self.del_resource(arn)
1✔
50

51

52
ResourceARN = str
1✔
53
TagKey = str
1✔
54
TagValue = str
1✔
55
TagMap = dict[TagKey, TagValue]
1✔
56

57

58
@dataclass
1✔
59
class Tags:
1✔
60
    """
61
    This dataclass provides utilities for performing resource tagging. Tags for resources are stored on
62
    the service provider's store within this `Tags` dataclass with ResourceARN mapped against a dictionary
63
    containing tags in the form TagKey:TagValue to remain agnostic to the service's tag format.
64

65
    The `Tags` dataclass supports updating / creating tags, deleting tags, and removing the
66
    resource from the tag dictionary (_tags). It's important that when a resource is deleted to remove this
67
    resource ARN from the store using the `delete_all_tags` method::
68

69
        store = get_store(account_id, region)
70
        store.TAGS.delete_all_tags(my_resource_arn)
71

72
    Do not use the `Tags` dataclass to determine the existence of a resource. For this, use ``connect_to`` or
73
    direct Moto Backend introspection. It's important that resources do not exist within _tags unless they
74
    currently have tags or have had tags in the past and the resource exists. The resource ARN should not exist within
75
    _tags if the resource has been deleted.
76

77
    This distinction is important to maintain parity with the Resource Groups Tagging API (RGTA) which will tap into
78
    supported service's `Tags` dataclass within it's store.
79
    """
80

81
    _tags: dict[ResourceARN, TagMap] = field(default_factory=dict)
1✔
82

83
    def update_tags(self, arn: ResourceARN, tags: TagMap) -> None:
1✔
84
        """
85
        Updates the tags of the specified resource.
86

87
        :param arn: The ARN of the resource to tag.
88
        :param tags: A mapping of tag keys to tag values or an array of tag objects.
89
        :return: None
90
        """
91
        stored_tags = self._tags.setdefault(arn, {})
1✔
92

93
        for k, v in tags.items():
1✔
94
            stored_tags[k] = v
1✔
95

96
    def get_tags(self, arn: ResourceARN) -> TagMap:
1✔
97
        """
98
        Retrieves the tags for a specified resource.
99

100
        The tags are returned as a flat map of tag key/value pairs, e.g.::
101
            {
102
                "Environment": "Production",
103
                "Owner": "LocalStack",
104
            }
105

106
        :param arn: The ARN of the resource you want to retrieve tags for.
107
        :return: A dictionary copy of tag keys to tag values for the resource.
108
        """
109
        if arn not in self._tags:
1✔
110
            return {}
1✔
111
        return self._tags[arn].copy()
1✔
112

113
    def delete_tags(self, arn: ResourceARN, keys: list[TagKey]) -> None:
1✔
114
        """
115
        Deletes the tag on the resource specified by the provided tag keys.
116

117
        :param arn: The ARN of the resource to remove tags for.
118
        :param keys: An array of tag keys to remove from the resource.
119
        :return: None
120
        """
121
        if tags := self._tags.get(arn):
1✔
122
            for key in keys:
1✔
123
                tags.pop(key, None)
1✔
124

125
    def delete_all_tags(self, arn: ResourceARN) -> None:
1✔
126
        """
127
        Removes all the tags for a resource and removes it from the internal tagging store.
128
        To be used once a resource is deleted or when you wish to remove all a resources tags.
129

130
        :param arn: The ARN of the resource to remove from the store.
131
        :return: None
132
        """
133
        self._tags.pop(arn, None)
1✔
134

135
    def get_resource_tag_map(self) -> dict[ResourceARN, TagMap]:
1✔
136
        """
137
        Retrieves the entire mapping between Resource ARNs and their tags.
138

139
        This should not be used to retrieve tags for a single resource and should instead use the
140
        `Tags.get_tags(resource_arn)`. It should only be used in scenarios where visibility into the
141
        entire internal tag store is required such as with the Resource Groups Tagging API (RGTA).
142

143
        :return: A mapping between Resource ARN and tags.
144
        """
145

146
        return self._tags.copy()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc