codinsight 0.0.9__tar.gz → 0.2.0__tar.gz

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.
Files changed (25) hide show
  1. {codinsight-0.0.9 → codinsight-0.2.0}/PKG-INFO +1 -1
  2. {codinsight-0.0.9 → codinsight-0.2.0}/pyproject.toml +1 -1
  3. codinsight-0.2.0/src/code_insight/code_analysis/abstract.py +91 -0
  4. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/algorithm.py +240 -31
  5. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/complexity.py +175 -23
  6. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/quality.py +205 -29
  7. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/readability.py +243 -31
  8. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/redundancy.py +143 -17
  9. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/struct.py +259 -41
  10. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/style.py +126 -18
  11. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/core.py +103 -13
  12. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/multi_analysis.py +164 -12
  13. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/trend_analysis/trend_analysis.py +78 -6
  14. {codinsight-0.0.9 → codinsight-0.2.0}/src/codinsight.egg-info/PKG-INFO +1 -1
  15. codinsight-0.0.9/src/code_insight/code_analysis/abstract.py +0 -38
  16. {codinsight-0.0.9 → codinsight-0.2.0}/README.md +0 -0
  17. {codinsight-0.0.9 → codinsight-0.2.0}/setup.cfg +0 -0
  18. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/__init__.py +0 -0
  19. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/code_analysis/__init__.py +0 -0
  20. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/py.typed +0 -0
  21. {codinsight-0.0.9 → codinsight-0.2.0}/src/code_insight/trend_analysis/__init__.py +0 -0
  22. {codinsight-0.0.9 → codinsight-0.2.0}/src/codinsight.egg-info/SOURCES.txt +0 -0
  23. {codinsight-0.0.9 → codinsight-0.2.0}/src/codinsight.egg-info/dependency_links.txt +0 -0
  24. {codinsight-0.0.9 → codinsight-0.2.0}/src/codinsight.egg-info/requires.txt +0 -0
  25. {codinsight-0.0.9 → codinsight-0.2.0}/src/codinsight.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codinsight
3
- Version: 0.0.9
3
+ Version: 0.2.0
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codinsight"
7
- version = "0.0.9"
7
+ version = "0.2.0"
8
8
  description = "Add your description here"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -0,0 +1,91 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Generic, TypeVar
3
+
4
+ from pydantic import BaseModel
5
+
6
+
7
+ class BaseAnalysisConfig(BaseModel):
8
+ """
9
+ 解析設定のベースクラス
10
+
11
+ Attributes
12
+ ----------
13
+ enabled : bool
14
+ 解析の有効/無効フラグ, by default True
15
+ """
16
+
17
+ enabled: bool = True
18
+
19
+
20
+ class BaseAnalysisResult(BaseModel):
21
+ """
22
+ 解析結果のベースモデル
23
+
24
+ Notes
25
+ -----
26
+ 全ての解析結果クラスの基底クラス
27
+ """
28
+
29
+
30
+ R = TypeVar("R", bound=BaseAnalysisResult)
31
+ C = TypeVar("C", bound=BaseAnalysisConfig)
32
+
33
+
34
+ class AbstractAnalysis(ABC, Generic[R, C]):
35
+ """
36
+ 解析抽象クラス
37
+
38
+ Parameters
39
+ ----------
40
+ R : TypeVar
41
+ 解析結果の型
42
+ C : TypeVar
43
+ 解析設定の型
44
+
45
+ Attributes
46
+ ----------
47
+ config : C
48
+ 解析設定
49
+ """
50
+
51
+ config: C
52
+
53
+ def __init__(self, config: C | None = None) -> None:
54
+ """
55
+ コンストラクタ
56
+
57
+ Parameters
58
+ ----------
59
+ config : C | None, optional
60
+ 解析設定, by default None
61
+ """
62
+ self.config = config or self.get_default_config()
63
+
64
+ @abstractmethod
65
+ def get_default_config(self) -> C:
66
+ """
67
+ デフォルト設定を取得
68
+
69
+ Returns
70
+ -------
71
+ C
72
+ デフォルト設定
73
+ """
74
+ raise NotImplementedError("get_default_config method must be implemented")
75
+
76
+ @abstractmethod
77
+ def analyze(self, source_code: str) -> R:
78
+ """
79
+ コードを解析する
80
+
81
+ Parameters
82
+ ----------
83
+ source_code : str
84
+ 解析対象のソースコード
85
+
86
+ Returns
87
+ -------
88
+ R
89
+ 解析結果
90
+ """
91
+ raise NotImplementedError("analyze method must be implemented")
@@ -11,8 +11,13 @@ from code_insight.code_analysis.abstract import (
11
11
  class AlgorithmAnalysisConfig(BaseAnalysisConfig):
12
12
  """
13
13
  アルゴリズム解析設定
14
- * 最大ネスト深度閾値
15
- * サイクロマティック複雑度閾値
14
+
15
+ Attributes
16
+ ----------
17
+ max_nesting_depth_threshold : int
18
+ 最大ネスト深度閾値, by default 4
19
+ cyclomatic_complexity_threshold : float
20
+ サイクロマティック複雑度閾値, by default 5.0
16
21
  """
17
22
 
18
23
  max_nesting_depth_threshold: int = 4
@@ -22,19 +27,27 @@ class AlgorithmAnalysisConfig(BaseAnalysisConfig):
22
27
  class AlgorithmAnalysisResult(BaseAnalysisResult):
23
28
  """
24
29
  解析結果(アルゴリズム)
25
- * 制御構文
26
- * if文の数
27
- * for文の数
28
- * while文の数
29
- * try-except文の数
30
- * 再帰構造
31
- * 再帰関数の割合
32
- * FP的要素
33
- * lambda式の数
34
- * リスト内包表記の数
35
- * map/filter/reduce呼び出しの数
36
- * ネスト深度
37
- * 制御構文の最大ネスト深度
30
+
31
+ Attributes
32
+ ----------
33
+ if_count : int
34
+ if文の数
35
+ for_count : int
36
+ for文の数
37
+ while_count : int
38
+ while文の数
39
+ try_count : int
40
+ try-except文の数
41
+ recursion_rate : float
42
+ 再帰関数の割合
43
+ lambda_count : int
44
+ lambda式の数
45
+ comprehension_count : int
46
+ リスト内包表記の数
47
+ functional_call_count : int
48
+ map/filter/reduce呼び出しの数
49
+ max_nesting_depth : int
50
+ 制御構文の最大ネスト深度
38
51
  """
39
52
 
40
53
  if_count: int
@@ -49,18 +62,50 @@ class AlgorithmAnalysisResult(BaseAnalysisResult):
49
62
 
50
63
 
51
64
  class Algorithm(AbstractAnalysis[AlgorithmAnalysisResult, AlgorithmAnalysisConfig]):
52
- """解析クラス(アルゴリズム)"""
65
+ """
66
+ 解析クラス(アルゴリズム)
67
+
68
+ Notes
69
+ -----
70
+ コードのアルゴリズム的特徴を多角的に解析するクラス
71
+ """
53
72
 
54
73
  def __init__(self, config: AlgorithmAnalysisConfig | None = None) -> None:
55
- """コンストラクタ"""
74
+ """
75
+ コンストラクタ
76
+
77
+ Parameters
78
+ ----------
79
+ config : AlgorithmAnalysisConfig | None, optional
80
+ アルゴリズム解析設定, by default None
81
+ """
56
82
  super().__init__(config)
57
83
 
58
84
  def get_default_config(self) -> AlgorithmAnalysisConfig:
59
- """デフォルト設定を取得"""
85
+ """
86
+ デフォルト設定を取得
87
+
88
+ Returns
89
+ -------
90
+ AlgorithmAnalysisConfig
91
+ デフォルトのアルゴリズム解析設定
92
+ """
60
93
  return AlgorithmAnalysisConfig()
61
94
 
62
95
  def analyze(self, source_code: str) -> AlgorithmAnalysisResult:
63
- """コード解析"""
96
+ """
97
+ コード解析
98
+
99
+ Parameters
100
+ ----------
101
+ source_code : str
102
+ 解析対象のソースコード
103
+
104
+ Returns
105
+ -------
106
+ AlgorithmAnalysisResult
107
+ アルゴリズム解析結果
108
+ """
64
109
  if not self.config.enabled:
65
110
  return AlgorithmAnalysisResult(
66
111
  if_count=0,
@@ -89,33 +134,115 @@ class Algorithm(AbstractAnalysis[AlgorithmAnalysisResult, AlgorithmAnalysisConfi
89
134
  )
90
135
 
91
136
  def parse_source_code(self, source_code: str) -> ast.AST:
92
- """ソースコードを解析"""
137
+ """
138
+ ソースコードを解析
139
+
140
+ Parameters
141
+ ----------
142
+ source_code : str
143
+ 解析対象のソースコード
144
+
145
+ Returns
146
+ -------
147
+ ast.AST
148
+ 解析済みのAST
149
+ """
93
150
  return ast.parse(source_code)
94
151
 
95
152
  def get_if_count(self, source_code: str, tree: ast.AST | None = None) -> int:
96
- """if文の数を取得"""
153
+ """
154
+ if文の数を取得
155
+
156
+ Parameters
157
+ ----------
158
+ source_code : str
159
+ 解析対象のソースコード
160
+ tree : ast.AST | None, optional
161
+ 解析済みのAST, by default None
162
+
163
+ Returns
164
+ -------
165
+ int
166
+ if文の数
167
+ """
97
168
  tree = tree or self.parse_source_code(source_code)
98
169
  return sum(isinstance(node, ast.If) for node in ast.walk(tree))
99
170
 
100
171
  def get_for_count(self, source_code: str, tree: ast.AST | None = None) -> int:
101
- """for文の数を取得"""
172
+ """
173
+ for文の数を取得
174
+
175
+ Parameters
176
+ ----------
177
+ source_code : str
178
+ 解析対象のソースコード
179
+ tree : ast.AST | None, optional
180
+ 解析済みのAST, by default None
181
+
182
+ Returns
183
+ -------
184
+ int
185
+ for文の数
186
+ """
102
187
  tree = tree or self.parse_source_code(source_code)
103
188
  return sum(isinstance(node, (ast.For, ast.AsyncFor)) for node in ast.walk(tree))
104
189
 
105
190
  def get_while_count(self, source_code: str, tree: ast.AST | None = None) -> int:
106
- """while文の数を取得"""
191
+ """
192
+ while文の数を取得
193
+
194
+ Parameters
195
+ ----------
196
+ source_code : str
197
+ 解析対象のソースコード
198
+ tree : ast.AST | None, optional
199
+ 解析済みのAST, by default None
200
+
201
+ Returns
202
+ -------
203
+ int
204
+ while文の数
205
+ """
107
206
  tree = tree or self.parse_source_code(source_code)
108
207
  return sum(isinstance(node, ast.While) for node in ast.walk(tree))
109
208
 
110
209
  def get_try_count(self, source_code: str, tree: ast.AST | None = None) -> int:
111
- """try-except文の数を取得"""
210
+ """
211
+ try-except文の数を取得
212
+
213
+ Parameters
214
+ ----------
215
+ source_code : str
216
+ 解析対象のソースコード
217
+ tree : ast.AST | None, optional
218
+ 解析済みのAST, by default None
219
+
220
+ Returns
221
+ -------
222
+ int
223
+ try-except文の数
224
+ """
112
225
  tree = tree or self.parse_source_code(source_code)
113
226
  return sum(isinstance(node, ast.Try) for node in ast.walk(tree))
114
227
 
115
228
  def get_recursion_rate(
116
229
  self, source_code: str, tree: ast.AST | None = None
117
230
  ) -> float:
118
- """再帰関数の割合を取得"""
231
+ """
232
+ 再帰関数の割合を取得
233
+
234
+ Parameters
235
+ ----------
236
+ source_code : str
237
+ 解析対象のソースコード
238
+ tree : ast.AST | None, optional
239
+ 解析済みのAST, by default None
240
+
241
+ Returns
242
+ -------
243
+ float
244
+ 再帰関数の割合
245
+ """
119
246
  tree = tree or self.parse_source_code(source_code)
120
247
  function_names: Set[str] = set()
121
248
  recursive_functions: Set[str] = set()
@@ -139,14 +266,42 @@ class Algorithm(AbstractAnalysis[AlgorithmAnalysisResult, AlgorithmAnalysisConfi
139
266
  return 0.0
140
267
 
141
268
  def get_lambda_count(self, source_code: str, tree: ast.AST | None = None) -> int:
142
- """lambda式の数を取得"""
269
+ """
270
+ lambda式の数を取得
271
+
272
+ Parameters
273
+ ----------
274
+ source_code : str
275
+ 解析対象のソースコード
276
+ tree : ast.AST | None, optional
277
+ 解析済みのAST, by default None
278
+
279
+ Returns
280
+ -------
281
+ int
282
+ lambda式の数
283
+ """
143
284
  tree = tree or self.parse_source_code(source_code)
144
285
  return sum(isinstance(node, ast.Lambda) for node in ast.walk(tree))
145
286
 
146
287
  def get_comprehension_count(
147
288
  self, source_code: str, tree: ast.AST | None = None
148
289
  ) -> int:
149
- """内包表記の数を取得"""
290
+ """
291
+ 内包表記の数を取得
292
+
293
+ Parameters
294
+ ----------
295
+ source_code : str
296
+ 解析対象のソースコード
297
+ tree : ast.AST | None, optional
298
+ 解析済みのAST, by default None
299
+
300
+ Returns
301
+ -------
302
+ int
303
+ 内包表記の数
304
+ """
150
305
  tree = tree or self.parse_source_code(source_code)
151
306
  return sum(
152
307
  isinstance(
@@ -158,7 +313,21 @@ class Algorithm(AbstractAnalysis[AlgorithmAnalysisResult, AlgorithmAnalysisConfi
158
313
  def get_functional_call_count(
159
314
  self, source_code: str, tree: ast.AST | None = None
160
315
  ) -> int:
161
- """map/filter/reduce呼び出しの数を取得"""
316
+ """
317
+ map/filter/reduce呼び出しの数を取得
318
+
319
+ Parameters
320
+ ----------
321
+ source_code : str
322
+ 解析対象のソースコード
323
+ tree : ast.AST | None, optional
324
+ 解析済みのAST, by default None
325
+
326
+ Returns
327
+ -------
328
+ int
329
+ map/filter/reduce呼び出しの数
330
+ """
162
331
  tree = tree or self.parse_source_code(source_code)
163
332
  functional_names = {"map", "filter", "reduce"}
164
333
  count = 0
@@ -176,7 +345,21 @@ class Algorithm(AbstractAnalysis[AlgorithmAnalysisResult, AlgorithmAnalysisConfi
176
345
  def get_cyclomatic_complexity(
177
346
  self, source_code: str, tree: ast.AST | None = None
178
347
  ) -> float:
179
- """循環的複雑度の平均を取得"""
348
+ """
349
+ 循環的複雑度の平均を取得
350
+
351
+ Parameters
352
+ ----------
353
+ source_code : str
354
+ 解析対象のソースコード
355
+ tree : ast.AST | None, optional
356
+ 解析済みのAST, by default None
357
+
358
+ Returns
359
+ -------
360
+ float
361
+ 循環的複雑度の平均
362
+ """
180
363
  tree = tree or self.parse_source_code(source_code)
181
364
  complexities = []
182
365
 
@@ -188,7 +371,19 @@ class Algorithm(AbstractAnalysis[AlgorithmAnalysisResult, AlgorithmAnalysisConfi
188
371
  return sum(complexities) / len(complexities) if complexities else 0.0
189
372
 
190
373
  def _calculate_function_complexity(self, func_node: ast.FunctionDef) -> int:
191
- """関数の循環的複雑度を計算"""
374
+ """
375
+ 関数の循環的複雑度を計算
376
+
377
+ Parameters
378
+ ----------
379
+ func_node : ast.FunctionDef
380
+ 関数定義ノード
381
+
382
+ Returns
383
+ -------
384
+ int
385
+ 循環的複雑度
386
+ """
192
387
  complexity = 1
193
388
 
194
389
  for node in ast.walk(func_node):
@@ -204,7 +399,21 @@ class Algorithm(AbstractAnalysis[AlgorithmAnalysisResult, AlgorithmAnalysisConfi
204
399
  def get_max_nesting_depth(
205
400
  self, source_code: str, tree: ast.AST | None = None
206
401
  ) -> int:
207
- """制御構文の最大ネスト深度を取得"""
402
+ """
403
+ 制御構文の最大ネスト深度を取得
404
+
405
+ Parameters
406
+ ----------
407
+ source_code : str
408
+ 解析対象のソースコード
409
+ tree : ast.AST | None, optional
410
+ 解析済みのAST, by default None
411
+
412
+ Returns
413
+ -------
414
+ int
415
+ 最大ネスト深度
416
+ """
208
417
  tree = tree or self.parse_source_code(source_code)
209
418
  max_depth = 0
210
419