From dd239b0473bcda3912ec5d11d75557208de40a1d Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Thu, 29 Jan 2026 13:53:44 +0000 Subject: [PATCH] Initial upload: API Mock CLI v0.1.0 --- src/core/matcher.py | 64 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/core/matcher.py diff --git a/src/core/matcher.py b/src/core/matcher.py new file mode 100644 index 0000000..9e51609 --- /dev/null +++ b/src/core/matcher.py @@ -0,0 +1,64 @@ +import re +from typing import Optional, Dict, Any, List +from src.models.endpoint import Endpoint + + +class Matcher: + HTTP_METHODS = ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] + + def __init__(self): + self.patterns: Dict[str, List[Dict[str, Any]]] = { + method: [] for method in self.HTTP_METHODS + } + + def compile_pattern(self, path: str) -> re.Pattern: + param_names = {} + regex_path = re.sub(r"\{(\w+)\}", lambda m: param_names.__setitem__(m.group(1), m.group(0)) or "(?P<" + m.group(1) + ">[^/]+)", path) + regex_path = f"^{regex_path}$" + return re.compile(regex_path) + + def add_endpoint(self, endpoint: Endpoint) -> None: + method = endpoint.method.upper() + if method not in self.HTTP_METHODS: + raise ValueError(f"Invalid HTTP method: {method}") + pattern = self.compile_pattern(endpoint.path) + self.patterns[method].append({ + "pattern": pattern, + "endpoint": endpoint, + "params": {} + }) + + def match(self, path: str, method: str) -> Optional[tuple[Endpoint, Dict[str, str]]]: + method = method.upper() + if method not in self.HTTP_METHODS: + return None + for route in self.patterns[method]: + match = route["pattern"].match(path) + if match: + return route["endpoint"], match.groupdict() + return None + + def get_endpoints(self, method: Optional[str] = None) -> List[Endpoint]: + if method: + method = method.upper() + return [r["endpoint"] for r in self.patterns.get(method, [])] + all_endpoints = [] + for routes in self.patterns.values(): + all_endpoints.extend(r["endpoint"] for r in routes) + return all_endpoints + + def remove_endpoint(self, path: str, method: str) -> bool: + method = method.upper() + original_count = len(self.patterns[method]) + self.patterns[method] = [ + r for r in self.patterns[method] + if r["endpoint"].path != path or r["endpoint"].method.upper() != method + ] + return len(self.patterns[method]) < original_count + + def clear(self, method: Optional[str] = None) -> None: + if method: + self.patterns[method.upper()] = [] + else: + for m in self.HTTP_METHODS: + self.patterns[m] = []