Skip to content

Instantly share code, notes, and snippets.

@pirogoeth
Created July 15, 2020 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pirogoeth/afb28316950a7878c93c907b031a6192 to your computer and use it in GitHub Desktop.
Save pirogoeth/afb28316950a7878c93c907b031a6192 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
import functools
import operator
from typing import Optional
ANY = object()
class regex:
""" super stupid regex class for equality checking
"""
def __init__(self, ptn):
self.ptn = ptn
def __repr__(self):
return f"/{self.ptn}/"
def __eq__(self, o):
return self.ptn == o
cases = [
(
"nomad.scale",
{"action": "nomad.scale", "params": {}},
),
(
"nomad.scale{}",
{"action": "nomad.scale", "params": {}},
),
(
"nomad.scale{region=/us-(east|west)-[12]/}",
{"action": "nomad.scale", "params": {
"region": regex("us-(east|west)-[12]"),
}}
),
(
"nomad.scale{region=*, service=\"usage\"}",
{"action": "nomad.scale", "params": {
"region": ANY, "service": "usage",
}}
),
(
"nomad.scale {}",
{"action": "nomad.scale", "params": {}},
),
(
"nomad.scale { region=* , service=* } ",
{"action": "nomad.scale", "params": {
"region": ANY, "service": ANY,
}}
),
(
"nomad.scale { region=*",
Exception,
),
(
"nomad.scale{regions=[us-east-1,us-west-2], service=\"usage\"}",
{"action": "nomad.scale", "params": {
"regions": ["us-east-1", "us-west-2"], "service": "usage",
}}
),
(
"nomad.scale { service=\"usage\" , region=* }",
{"action": "nomad.scale", "params": {
"service": "usage", "region": ANY,
}}
)
]
def parse(spec: str) -> dict:
""" Parses an action specifier string into dictionary representation
"""
try:
params_start = spec.index("{")
except ValueError:
# This is just a plain action
return {"action": spec, "params": {}}
try:
params_end = spec.rindex("}")
except ValueError as err:
# Missing ending brace
raise Exception(f"Action spec is missing an ending brace: {spec=}") from err
action = spec[:params_start].strip()
params_str = spec[params_start+1:params_end].strip()
params = {}
while True:
if not params_str:
break
key, rest = params_str.split("=", 1)
key = key.strip()
# Peek ahead to determine the value type
if rest[0] == "/":
rest = rest[1:]
end = find_next_unescaped(rest, "/")
if end is None:
raise Exception(f"Unmatched `/` in spec: {spec=}")
value = rest[:end]
rest = rest[end+1:]
value = regex(value)
elif rest[0] == "[":
rest = rest[1:]
end = find_next_unescaped(rest, "]")
if end is None:
raise Exception(f"Unmatched `]` in spec: {spec=}")
value = rest[:end]
rest = rest[end+1:]
value = value.split(",")
value = [item.strip() for item in value]
elif rest[0] == "\"":
rest = rest[1:]
end = find_next_unescaped(rest, "\"")
if end is None:
raise Exception(f"Unmatched `\"` in spec: {spec=}")
value = rest[:end]
rest = rest[end+1:]
elif rest[0] == "*":
rest = rest[1:]
value = ANY
if len(rest.strip()) > 1 and rest.strip()[0] == ",":
rest = rest.strip()[1:].lstrip()
params[key] = value
params_str = rest
return {
"action": action,
"params": params,
}
def find_next_unescaped(haystack: str, needle: str) -> Optional[int]:
escapes = 0
for idx, char in enumerate(haystack):
if char == needle and escapes % 2 == 0:
return idx
elif char == "\\":
escapes += 1
else:
escapes = 0
return None
def assertEq(value, expected):
ok = "✔️"
fail = "❌"
if value == expected:
print(f" {ok}\t{value=} == {expected=}")
else:
print(f" {fail}\t{value=} != {expected=}")
for test, expectation in cases:
print(f" -> {test}")
try:
if issubclass(expectation, Exception):
try:
parse(test)
except Exception as err:
assertEq(isinstance(err, expectation), True)
else:
# wut
raise "fuck"
except TypeError:
received = parse(test)
assertEq(received, expectation)
[sean:...ts/mailgun/director-chatops] λ python director_chatops/util/abac/naive.py ( ⇌ master ✱ ) (director-chatops)
-> nomad.scale
✔️ value={'action': 'nomad.scale', 'params': {}} == expected={'action': 'nomad.scale', 'params': {}}
-> nomad.scale{}
✔️ value={'action': 'nomad.scale', 'params': {}} == expected={'action': 'nomad.scale', 'params': {}}
-> nomad.scale{region=/us-(east|west)-[12]/}
✔️ value={'action': 'nomad.scale', 'params': {'region': /us-(east|west)-[12]/}} == expected={'action': 'nomad.scale', 'params': {'region': /us-(east|west)-[12]/}}
-> nomad.scale{region=*, service="usage"}
✔️ value={'action': 'nomad.scale', 'params': {'region': <object object at 0x10324eec0>, 'service': 'usage'}} == expected={'action': 'nomad.scale', 'params': {'region': <object object at 0x10324eec0>, 'service': 'usage'}}
-> nomad.scale {}
✔️ value={'action': 'nomad.scale', 'params': {}} == expected={'action': 'nomad.scale', 'params': {}}
-> nomad.scale { region=* , service=* }
✔️ value={'action': 'nomad.scale', 'params': {'region': <object object at 0x10324eec0>, 'service': <object object at 0x10324eec0>}} == expected={'action': 'nomad.scale', 'params': {'region': <object object at 0x10324eec0>, 'service': <object object at 0x10324eec0>}}
-> nomad.scale { region=*
✔️ value=True == expected=True
-> nomad.scale{regions=[us-east-1,us-west-2], service="usage"}
✔️ value={'action': 'nomad.scale', 'params': {'regions': ['us-east-1', 'us-west-2'], 'service': 'usage'}} == expected={'action': 'nomad.scale', 'params': {'regions': ['us-east-1', 'us-west-2'], 'service': 'usage'}}
-> nomad.scale { service="usage" , region=* }
✔️ value={'action': 'nomad.scale', 'params': {'service': 'usage', 'region': <object object at 0x10324eec0>}} == expected={'action': 'nomad.scale', 'params': {'service': 'usage', 'region': <object object at 0x10324eec0>}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment