cicada-mcp 0.1.4__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.

Potentially problematic release.


This version of cicada-mcp might be problematic. Click here for more details.

Files changed (48) hide show
  1. cicada/__init__.py +30 -0
  2. cicada/clean.py +297 -0
  3. cicada/command_logger.py +293 -0
  4. cicada/dead_code_analyzer.py +282 -0
  5. cicada/extractors/__init__.py +36 -0
  6. cicada/extractors/base.py +66 -0
  7. cicada/extractors/call.py +176 -0
  8. cicada/extractors/dependency.py +361 -0
  9. cicada/extractors/doc.py +179 -0
  10. cicada/extractors/function.py +246 -0
  11. cicada/extractors/module.py +123 -0
  12. cicada/extractors/spec.py +151 -0
  13. cicada/find_dead_code.py +270 -0
  14. cicada/formatter.py +918 -0
  15. cicada/git_helper.py +646 -0
  16. cicada/indexer.py +629 -0
  17. cicada/install.py +724 -0
  18. cicada/keyword_extractor.py +364 -0
  19. cicada/keyword_search.py +553 -0
  20. cicada/lightweight_keyword_extractor.py +298 -0
  21. cicada/mcp_server.py +1559 -0
  22. cicada/mcp_tools.py +291 -0
  23. cicada/parser.py +124 -0
  24. cicada/pr_finder.py +435 -0
  25. cicada/pr_indexer/__init__.py +20 -0
  26. cicada/pr_indexer/cli.py +62 -0
  27. cicada/pr_indexer/github_api_client.py +431 -0
  28. cicada/pr_indexer/indexer.py +297 -0
  29. cicada/pr_indexer/line_mapper.py +209 -0
  30. cicada/pr_indexer/pr_index_builder.py +253 -0
  31. cicada/setup.py +339 -0
  32. cicada/utils/__init__.py +52 -0
  33. cicada/utils/call_site_formatter.py +95 -0
  34. cicada/utils/function_grouper.py +57 -0
  35. cicada/utils/hash_utils.py +173 -0
  36. cicada/utils/index_utils.py +290 -0
  37. cicada/utils/path_utils.py +240 -0
  38. cicada/utils/signature_builder.py +106 -0
  39. cicada/utils/storage.py +111 -0
  40. cicada/utils/subprocess_runner.py +182 -0
  41. cicada/utils/text_utils.py +90 -0
  42. cicada/version_check.py +116 -0
  43. cicada_mcp-0.1.4.dist-info/METADATA +619 -0
  44. cicada_mcp-0.1.4.dist-info/RECORD +48 -0
  45. cicada_mcp-0.1.4.dist-info/WHEEL +5 -0
  46. cicada_mcp-0.1.4.dist-info/entry_points.txt +8 -0
  47. cicada_mcp-0.1.4.dist-info/licenses/LICENSE +21 -0
  48. cicada_mcp-0.1.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,90 @@
1
+ """
2
+ Text utilities for identifier manipulation and processing.
3
+
4
+ This module provides shared utilities for working with code identifiers,
5
+ including splitting camelCase, PascalCase, and snake_case identifiers.
6
+ """
7
+
8
+ import re
9
+ from typing import List
10
+
11
+
12
+ def split_identifier(identifier: str, lowercase: bool = True) -> List[str]:
13
+ """
14
+ Split an identifier by camelCase, PascalCase, and snake_case.
15
+
16
+ Handles various identifier patterns:
17
+ - snake_case: get_user_data -> ['get', 'user', 'data']
18
+ - camelCase: getUserData -> ['get', 'user', 'data']
19
+ - PascalCase: UserController -> ['user', 'controller']
20
+ - HTTPServer: HTTP Server -> ['http', 'server']
21
+ - PostgreSQL: Postgre SQL -> ['postgre', 'sql']
22
+ - getHTTPResponseCode -> ['get', 'http', 'response', 'code']
23
+
24
+ Args:
25
+ identifier: The identifier string to split
26
+ lowercase: If True, convert all words to lowercase (default: True)
27
+
28
+ Returns:
29
+ List of words from the identifier
30
+
31
+ Examples:
32
+ >>> split_identifier("getUserData")
33
+ ['get', 'user', 'data']
34
+ >>> split_identifier("HTTPServer")
35
+ ['http', 'server']
36
+ >>> split_identifier("snake_case_name")
37
+ ['snake', 'case', 'name']
38
+ """
39
+ if not identifier:
40
+ return []
41
+
42
+ # Handle snake_case
43
+ text = identifier.replace("_", " ")
44
+
45
+ # Split on transitions from lowercase to uppercase (camelCase)
46
+ # This handles: camelCase, PascalCase, and words ending with uppercase like PostgreSQL
47
+ text = re.sub(r"([a-z])([A-Z])", r"\1 \2", text)
48
+
49
+ # Split on transitions from uppercase sequence to a capitalized word (HTTPServer -> HTTP Server)
50
+ text = re.sub(r"([A-Z]+)([A-Z][a-z])", r"\1 \2", text)
51
+
52
+ # Split consecutive uppercase letters to separate potential acronyms
53
+ # This helps extract individual letters from acronyms at the end (e.g., SQL -> S Q L)
54
+ # But only if they're part of a longer word (not standalone acronyms)
55
+ text = re.sub(r"(?<=[a-z])([A-Z])(?=[A-Z])", r" \1", text)
56
+
57
+ # Split and filter
58
+ words = text.split()
59
+
60
+ if lowercase:
61
+ words = [word.lower() for word in words if word]
62
+ else:
63
+ words = [word for word in words if word]
64
+
65
+ return words
66
+
67
+
68
+ def split_camel_snake_case(text: str) -> str:
69
+ """
70
+ Split camelCase, PascalCase, and snake_case identifiers into separate words as a string.
71
+
72
+ This is a convenience wrapper around split_identifier() that returns a space-separated
73
+ string instead of a list.
74
+
75
+ Args:
76
+ text: Input text containing identifiers
77
+
78
+ Returns:
79
+ String with identifiers split into separate words
80
+
81
+ Examples:
82
+ >>> split_camel_snake_case("camelCase")
83
+ 'camel case'
84
+ >>> split_camel_snake_case("PascalCase")
85
+ 'pascal case'
86
+ >>> split_camel_snake_case("snake_case")
87
+ 'snake case'
88
+ """
89
+ words = split_identifier(text, lowercase=True)
90
+ return " ".join(words)
@@ -0,0 +1,116 @@
1
+ """
2
+ Version checking utility.
3
+
4
+ Checks if a newer version of cicada is available on GitHub.
5
+ """
6
+
7
+ import subprocess
8
+ from typing import Optional
9
+
10
+
11
+ def get_current_version() -> str:
12
+ """
13
+ Get the current version of cicada from pyproject.toml.
14
+
15
+ Returns:
16
+ Current version string (e.g., "0.1.0")
17
+ """
18
+ from cicada import __version__
19
+
20
+ return __version__
21
+
22
+
23
+ def get_latest_github_tag(repo: str = "wende/cicada") -> Optional[str]:
24
+ """
25
+ Get the latest tag from GitHub repository.
26
+
27
+ Args:
28
+ repo: GitHub repository in format "owner/repo"
29
+
30
+ Returns:
31
+ Latest tag name, or None if unable to fetch
32
+ """
33
+ try:
34
+ result = subprocess.run(
35
+ [
36
+ "gh",
37
+ "api",
38
+ f"repos/{repo}/tags",
39
+ "--jq",
40
+ ".[0].name",
41
+ ],
42
+ capture_output=True,
43
+ text=True,
44
+ timeout=5,
45
+ )
46
+
47
+ if result.returncode == 0 and result.stdout.strip():
48
+ tag = result.stdout.strip()
49
+ # Remove 'v' prefix if present (e.g., "v0.1.0" -> "0.1.0")
50
+ if tag.startswith("v"):
51
+ tag = tag[1:]
52
+ return tag
53
+
54
+ return None
55
+
56
+ except (subprocess.TimeoutExpired, FileNotFoundError, Exception):
57
+ # Silently fail - this is a non-critical check
58
+ return None
59
+
60
+
61
+ def compare_versions(current: str, latest: str) -> bool:
62
+ """
63
+ Compare two version strings.
64
+
65
+ Args:
66
+ current: Current version (e.g., "0.1.0")
67
+ latest: Latest version (e.g., "0.2.0")
68
+
69
+ Returns:
70
+ True if latest is newer than current, False otherwise
71
+ """
72
+ try:
73
+ # Simple comparison by splitting on dots
74
+ current_parts = [int(x) for x in current.split(".")]
75
+ latest_parts = [int(x) for x in latest.split(".")]
76
+
77
+ # Pad with zeros if needed
78
+ max_len = max(len(current_parts), len(latest_parts))
79
+ current_parts += [0] * (max_len - len(current_parts))
80
+ latest_parts += [0] * (max_len - len(latest_parts))
81
+
82
+ return latest_parts > current_parts
83
+
84
+ except (ValueError, AttributeError):
85
+ # If we can't parse versions, assume they're the same
86
+ return False
87
+
88
+
89
+ def check_for_updates() -> None:
90
+ """
91
+ Check if there's a newer version available on GitHub.
92
+
93
+ Prints a yellow warning message if a newer version is found.
94
+ This function never raises exceptions - it fails silently if unable to check.
95
+ """
96
+ try:
97
+ current = get_current_version()
98
+ latest = get_latest_github_tag()
99
+
100
+ if latest and compare_versions(current, latest):
101
+ # ANSI escape code for yellow text
102
+ yellow = "\033[93m"
103
+ reset = "\033[0m"
104
+
105
+ print(
106
+ f"{yellow}⚠️ A newer version of cicada is available: v{latest} (current: v{current}){reset}"
107
+ )
108
+ print(f"{yellow} To update, run:{reset}")
109
+ print(
110
+ f"{yellow} uv tool install git+https://github.com/wende/cicada.git{reset}"
111
+ )
112
+ print()
113
+
114
+ except Exception:
115
+ # Silently fail - version check is non-critical
116
+ pass