arnmatch 0.1.0__py3-none-any.whl → 0.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- arnmatch/__init__.py +28 -28
- arnmatch-0.3.1.dist-info/METADATA +108 -0
- arnmatch-0.3.1.dist-info/RECORD +6 -0
- arnmatch-0.1.0.dist-info/METADATA +0 -6
- arnmatch-0.1.0.dist-info/RECORD +0 -6
- {arnmatch-0.1.0.dist-info → arnmatch-0.3.1.dist-info}/WHEEL +0 -0
- {arnmatch-0.1.0.dist-info → arnmatch-0.3.1.dist-info}/entry_points.txt +0 -0
arnmatch/__init__.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""ARN pattern matching using regex patterns."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.1
|
|
3
|
+
__version__ = "0.3.1"
|
|
4
4
|
|
|
5
5
|
import sys
|
|
6
6
|
from dataclasses import dataclass
|
|
@@ -12,23 +12,23 @@ from .arn_patterns import ARN_PATTERNS
|
|
|
12
12
|
STANDARD_GROUPS = {"Partition", "Region", "Account"}
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class
|
|
16
|
-
"""Raised when ARN cannot be matched."""
|
|
15
|
+
class ARNError(ValueError):
|
|
16
|
+
"""Raised when ARN cannot be parsed or matched."""
|
|
17
17
|
|
|
18
18
|
pass
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
@dataclass(frozen=True)
|
|
22
|
-
class
|
|
23
|
-
"""
|
|
22
|
+
class ARN:
|
|
23
|
+
"""Parsed ARN with structured data and captured groups."""
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
aws_partition: str
|
|
26
|
+
aws_service: str
|
|
27
|
+
aws_region: str
|
|
28
|
+
aws_account: str
|
|
29
29
|
resource_type: str # canonical type (from AWS docs)
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
resource_types: list[str] # all known names including Resource Explorer
|
|
31
|
+
attributes: dict[str, str]
|
|
32
32
|
|
|
33
33
|
@cached_property
|
|
34
34
|
def resource_id(self) -> str:
|
|
@@ -39,7 +39,7 @@ class ARNMatch:
|
|
|
39
39
|
2. Group ending with 'Name' as fallback
|
|
40
40
|
3. Last non-standard group
|
|
41
41
|
"""
|
|
42
|
-
resource_groups = list(self.
|
|
42
|
+
resource_groups = list(self.attributes.items())
|
|
43
43
|
resource_groups = [(k, v) for k, v in resource_groups if k not in STANDARD_GROUPS]
|
|
44
44
|
|
|
45
45
|
# Look for *Id (from end)
|
|
@@ -66,7 +66,7 @@ class ARNMatch:
|
|
|
66
66
|
1. Group ending with 'Name' (FunctionName, BucketName, StackName)
|
|
67
67
|
2. Falls back to resource_id
|
|
68
68
|
"""
|
|
69
|
-
resource_groups = list(self.
|
|
69
|
+
resource_groups = list(self.attributes.items())
|
|
70
70
|
resource_groups = [(k, v) for k, v in resource_groups if k not in STANDARD_GROUPS]
|
|
71
71
|
|
|
72
72
|
# Look for *Name (from end)
|
|
@@ -78,7 +78,7 @@ class ARNMatch:
|
|
|
78
78
|
return self.resource_id
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
def arnmatch(arn: str) ->
|
|
81
|
+
def arnmatch(arn: str) -> ARN:
|
|
82
82
|
"""Match ARN against patterns.
|
|
83
83
|
|
|
84
84
|
Returns ARNMatch with all captured groups.
|
|
@@ -88,27 +88,27 @@ def arnmatch(arn: str) -> ARNMatch:
|
|
|
88
88
|
"""
|
|
89
89
|
parts = arn.split(":", 5)
|
|
90
90
|
if len(parts) != 6 or parts[0] != "arn":
|
|
91
|
-
raise
|
|
91
|
+
raise ARNError(f"Invalid ARN format: {arn}")
|
|
92
92
|
|
|
93
93
|
_, partition, service, region, account, _ = parts
|
|
94
94
|
|
|
95
95
|
if service not in ARN_PATTERNS:
|
|
96
|
-
raise
|
|
96
|
+
raise ARNError(f"Unknown service: {service}")
|
|
97
97
|
|
|
98
98
|
for regex, type_names in ARN_PATTERNS[service]:
|
|
99
99
|
match = regex.match(arn)
|
|
100
100
|
if match:
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
return ARN(
|
|
102
|
+
aws_partition=partition,
|
|
103
|
+
aws_service=service,
|
|
104
|
+
aws_region=region,
|
|
105
|
+
aws_account=account,
|
|
106
106
|
resource_type=type_names[0], # canonical
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
resource_types=type_names, # all known names
|
|
108
|
+
attributes=match.groupdict(),
|
|
109
109
|
)
|
|
110
110
|
|
|
111
|
-
raise
|
|
111
|
+
raise ARNError(f"No pattern matched ARN: {arn}")
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
def main() -> None:
|
|
@@ -120,12 +120,12 @@ def main() -> None:
|
|
|
120
120
|
arn = sys.argv[1]
|
|
121
121
|
try:
|
|
122
122
|
result = arnmatch(arn)
|
|
123
|
-
print(f"
|
|
124
|
-
print(f"
|
|
125
|
-
print(f"
|
|
123
|
+
print(f"aws_service: {result.aws_service}")
|
|
124
|
+
print(f"aws_region: {result.aws_region}")
|
|
125
|
+
print(f"aws_account: {result.aws_account}")
|
|
126
126
|
print(f"resource_type: {result.resource_type}")
|
|
127
127
|
print(f"resource_id: {result.resource_id}")
|
|
128
128
|
print(f"resource_name: {result.resource_name}")
|
|
129
|
-
except
|
|
129
|
+
except ARNError as e:
|
|
130
130
|
print(f"Error: {e}", file=sys.stderr)
|
|
131
131
|
sys.exit(1)
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: arnmatch
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: Parse AWS ARNs into structured data
|
|
5
|
+
Author-email: Andrey Gubarev <andrey@andreygubarev.com>
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
|
|
9
|
+
# arnmatch
|
|
10
|
+
|
|
11
|
+
Parse AWS ARNs into structured data.
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- Zero runtime dependencies
|
|
18
|
+
- 300+ AWS services, 2000+ resource types supported
|
|
19
|
+
- Patterns auto-generated from AWS official documentation
|
|
20
|
+
- CLI and library interface
|
|
21
|
+
- Extracts resource type, ID, and name with smart heuristics
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install arnmatch
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
### CLI
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
$ uvx arnmatch "arn:aws:lambda:us-east-1:123456789012:function:my-function"
|
|
35
|
+
aws_service: lambda
|
|
36
|
+
aws_region: us-east-1
|
|
37
|
+
aws_account: 123456789012
|
|
38
|
+
resource_type: function
|
|
39
|
+
resource_id: my-function
|
|
40
|
+
resource_name: my-function
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Library
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from arnmatch import arnmatch
|
|
47
|
+
|
|
48
|
+
arn = "arn:aws:lambda:us-east-1:123456789012:function:my-function"
|
|
49
|
+
result = arnmatch(arn)
|
|
50
|
+
|
|
51
|
+
print(result.aws_service) # lambda
|
|
52
|
+
print(result.aws_region) # us-east-1
|
|
53
|
+
print(result.aws_account) # 123456789012
|
|
54
|
+
print(result.resource_type) # function
|
|
55
|
+
print(result.resource_id) # my-function
|
|
56
|
+
print(result.resource_name) # my-function
|
|
57
|
+
print(result.attributes) # {'Partition': 'aws', 'Region': 'us-east-1', ...}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## API Reference
|
|
61
|
+
|
|
62
|
+
### `arnmatch(arn: str) -> ARN`
|
|
63
|
+
|
|
64
|
+
Parse an ARN string and return structured data.
|
|
65
|
+
|
|
66
|
+
Raises `ARNError` if the ARN format is invalid or no pattern matches.
|
|
67
|
+
|
|
68
|
+
### `ARN`
|
|
69
|
+
|
|
70
|
+
Dataclass with parsed ARN components:
|
|
71
|
+
|
|
72
|
+
| Field | Type | Description |
|
|
73
|
+
|-------|------|-------------|
|
|
74
|
+
| `aws_partition` | `str` | AWS partition (aws, aws-cn, aws-us-gov) |
|
|
75
|
+
| `aws_service` | `str` | AWS service name |
|
|
76
|
+
| `aws_region` | `str` | AWS region (may be empty for global resources) |
|
|
77
|
+
| `aws_account` | `str` | AWS account ID |
|
|
78
|
+
| `resource_type` | `str` | Canonical resource type from AWS docs |
|
|
79
|
+
| `resource_types` | `list[str]` | All known names for this resource type |
|
|
80
|
+
| `attributes` | `dict[str, str]` | All captured attributes from the pattern |
|
|
81
|
+
|
|
82
|
+
Properties:
|
|
83
|
+
|
|
84
|
+
| Property | Description |
|
|
85
|
+
|----------|-------------|
|
|
86
|
+
| `resource_id` | Resource identifier (prefers groups ending in `Id`, falls back to `Name`, then last group) |
|
|
87
|
+
| `resource_name` | Resource name (prefers groups ending in `Name`, falls back to `resource_id`) |
|
|
88
|
+
|
|
89
|
+
### `ARNError`
|
|
90
|
+
|
|
91
|
+
Exception raised when ARN parsing fails. Inherits from `ValueError`.
|
|
92
|
+
|
|
93
|
+
## Development
|
|
94
|
+
|
|
95
|
+
Prerequisites: [uv](https://github.com/astral-sh/uv)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
make lint # Run ruff linter
|
|
99
|
+
make build # Build wheel and tarball
|
|
100
|
+
make publish # Build and upload to PyPI
|
|
101
|
+
make clean # Remove build artifacts
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Regenerate patterns from AWS docs:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
cd codegen && uv run codegen.py
|
|
108
|
+
```
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
arnmatch/__init__.py,sha256=0wjjGQPi3iz4yhfQOyuPPECSEIwTY7dbVDIJE-EANSU,3926
|
|
2
|
+
arnmatch/arn_patterns.py,sha256=_1ZzNbqTrHWrdMMQAvpu78cdrNmsLaFSpae3auPA7cI,351568
|
|
3
|
+
arnmatch-0.3.1.dist-info/METADATA,sha256=G-8engLIim1QdU1uw45dxATlFOIuT-Y3iAPZpjyIPdY,2790
|
|
4
|
+
arnmatch-0.3.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
5
|
+
arnmatch-0.3.1.dist-info/entry_points.txt,sha256=k4tR_yh3Rodi-BfwVhc_6TktgYhE7BfMy6s0Zzq6EFk,43
|
|
6
|
+
arnmatch-0.3.1.dist-info/RECORD,,
|
arnmatch-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
arnmatch/__init__.py,sha256=9vV1dvwFOBkDktGOpwqeGR1Ele4IcEC246jbZEykL2Y,3889
|
|
2
|
-
arnmatch/arn_patterns.py,sha256=_1ZzNbqTrHWrdMMQAvpu78cdrNmsLaFSpae3auPA7cI,351568
|
|
3
|
-
arnmatch-0.1.0.dist-info/METADATA,sha256=-yenV5wvn8MVv7OXaSlQCo1wjDSfRAKCkQdgpAo88Kg,205
|
|
4
|
-
arnmatch-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
5
|
-
arnmatch-0.1.0.dist-info/entry_points.txt,sha256=k4tR_yh3Rodi-BfwVhc_6TktgYhE7BfMy6s0Zzq6EFk,43
|
|
6
|
-
arnmatch-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|