janito 0.5.0__py3-none-any.whl → 0.6.0__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.
Files changed (106) hide show
  1. janito/__init__.py +0 -47
  2. janito/__main__.py +96 -15
  3. janito/agents/__init__.py +2 -8
  4. janito/agents/claudeai.py +3 -12
  5. janito/change/__init__.py +29 -16
  6. janito/change/__main__.py +0 -0
  7. janito/{analysis → change/analysis}/__init__.py +5 -15
  8. janito/change/analysis/__main__.py +7 -0
  9. janito/change/analysis/analyze.py +61 -0
  10. janito/change/analysis/formatting.py +78 -0
  11. janito/change/analysis/options.py +81 -0
  12. janito/{analysis → change/analysis}/prompts.py +35 -12
  13. janito/change/analysis/view/__init__.py +9 -0
  14. janito/change/analysis/view/terminal.py +171 -0
  15. janito/change/applier/__init__.py +5 -0
  16. janito/change/applier/file.py +58 -0
  17. janito/change/applier/main.py +156 -0
  18. janito/change/applier/text.py +245 -0
  19. janito/change/applier/workspace_dir.py +58 -0
  20. janito/change/core.py +131 -0
  21. janito/{changehistory.py → change/history.py} +12 -14
  22. janito/change/operations.py +7 -0
  23. janito/change/parser.py +289 -0
  24. janito/change/play.py +54 -0
  25. janito/change/preview.py +82 -0
  26. janito/change/prompts.py +126 -0
  27. janito/change/test.py +0 -0
  28. janito/change/validator.py +251 -0
  29. janito/{changeviewer → change/viewer}/__init__.py +3 -4
  30. janito/change/viewer/content.py +66 -0
  31. janito/{changeviewer → change/viewer}/diff.py +19 -4
  32. janito/change/viewer/pager.py +56 -0
  33. janito/change/viewer/panels.py +555 -0
  34. janito/change/viewer/styling.py +103 -0
  35. janito/{changeviewer → change/viewer}/themes.py +3 -5
  36. janito/clear_statement_parser/clear_statement_format.txt +328 -0
  37. janito/clear_statement_parser/examples.txt +326 -0
  38. janito/clear_statement_parser/models.py +104 -0
  39. janito/clear_statement_parser/parser.py +496 -0
  40. janito/cli/base.py +30 -0
  41. janito/cli/commands.py +30 -38
  42. janito/cli/functions.py +19 -194
  43. janito/cli/handlers/ask.py +22 -0
  44. janito/cli/handlers/demo.py +22 -0
  45. janito/cli/handlers/request.py +24 -0
  46. janito/cli/handlers/scan.py +9 -0
  47. janito/cli/history.py +61 -0
  48. janito/common.py +34 -3
  49. janito/config.py +71 -6
  50. janito/demo/__init__.py +4 -0
  51. janito/demo/data.py +13 -0
  52. janito/demo/mock_data.py +20 -0
  53. janito/demo/operations.py +45 -0
  54. janito/demo/runner.py +59 -0
  55. janito/demo/scenarios.py +32 -0
  56. janito/prompts.py +1 -80
  57. janito/qa.py +4 -3
  58. janito/search_replace/README.md +146 -0
  59. janito/search_replace/__init__.py +6 -0
  60. janito/search_replace/__main__.py +21 -0
  61. janito/search_replace/core.py +119 -0
  62. janito/search_replace/parser.py +52 -0
  63. janito/search_replace/play.py +61 -0
  64. janito/search_replace/replacer.py +36 -0
  65. janito/search_replace/searcher.py +299 -0
  66. janito/shell/__init__.py +39 -0
  67. janito/shell/bus.py +31 -0
  68. janito/shell/commands.py +195 -0
  69. janito/shell/handlers.py +122 -0
  70. janito/shell/history.py +20 -0
  71. janito/shell/processor.py +52 -0
  72. janito/tui/__init__.py +21 -0
  73. janito/tui/base.py +22 -0
  74. janito/tui/flows/__init__.py +5 -0
  75. janito/tui/flows/changes.py +65 -0
  76. janito/tui/flows/content.py +128 -0
  77. janito/tui/flows/selection.py +117 -0
  78. janito/tui/screens/__init__.py +3 -0
  79. janito/tui/screens/app.py +1 -0
  80. janito/workspace/__init__.py +7 -0
  81. janito/workspace/analysis.py +121 -0
  82. janito/workspace/manager.py +48 -0
  83. janito/workspace/scan.py +232 -0
  84. janito-0.6.0.dist-info/METADATA +185 -0
  85. janito-0.6.0.dist-info/RECORD +95 -0
  86. {janito-0.5.0.dist-info → janito-0.6.0.dist-info}/WHEEL +1 -1
  87. janito/_contextparser.py +0 -113
  88. janito/analysis/display.py +0 -149
  89. janito/analysis/options.py +0 -112
  90. janito/change/applier.py +0 -269
  91. janito/change/content.py +0 -62
  92. janito/change/indentation.py +0 -33
  93. janito/change/position.py +0 -169
  94. janito/changeviewer/panels.py +0 -268
  95. janito/changeviewer/styling.py +0 -59
  96. janito/console/__init__.py +0 -3
  97. janito/console/commands.py +0 -112
  98. janito/console/core.py +0 -62
  99. janito/console/display.py +0 -157
  100. janito/fileparser.py +0 -334
  101. janito/scan.py +0 -176
  102. janito/tests/test_fileparser.py +0 -26
  103. janito-0.5.0.dist-info/METADATA +0 -146
  104. janito-0.5.0.dist-info/RECORD +0 -45
  105. {janito-0.5.0.dist-info → janito-0.6.0.dist-info}/entry_points.txt +0 -0
  106. {janito-0.5.0.dist-info → janito-0.6.0.dist-info}/licenses/LICENSE +0 -0
janito/scan.py DELETED
@@ -1,176 +0,0 @@
1
- from pathlib import Path
2
- from typing import List, Tuple, Set
3
- from rich.console import Console
4
- from rich.columns import Columns
5
- from rich.panel import Panel
6
- from janito.config import config
7
- from pathspec import PathSpec
8
- from pathspec.patterns import GitWildMatchPattern
9
- from collections import defaultdict
10
-
11
-
12
-
13
- SPECIAL_FILES = ["README.md", "__init__.py", "__main__.py"]
14
-
15
- def _scan_paths(paths: List[Path], workdir: Path = None) -> Tuple[List[str], List[str]]:
16
- """Common scanning logic used by both preview and content collection"""
17
- content_parts = []
18
- file_items = []
19
- skipped_files = []
20
- processed_files: Set[Path] = set() # Track processed files
21
- console = Console()
22
-
23
- # Load gitignore if it exists
24
- gitignore_path = workdir / '.gitignore' if workdir else None
25
- gitignore_spec = None
26
- if (gitignore_path and gitignore_path.exists()):
27
- with open(gitignore_path) as f:
28
- gitignore = f.read()
29
- gitignore_spec = PathSpec.from_lines(GitWildMatchPattern, gitignore.splitlines())
30
-
31
-
32
- def scan_path(path: Path, level: int) -> None:
33
- """
34
- Scan a path and add it to the content_parts list
35
- level 0 means we are scanning the root directory
36
- level 1 we provide both directory directory name and file content
37
- level > 1 we just return
38
- """
39
- if level > 1:
40
- return
41
-
42
- path = path.resolve()
43
- relative_base = workdir
44
- if path.is_dir():
45
- relative_path = path.relative_to(relative_base)
46
- content_parts.append(f'<directory><path>{relative_path}</path>not sent</directory>')
47
- file_items.append(f"[blue]•[/blue] {relative_path}/")
48
- # Check for special files
49
- special_found = []
50
- for special_file in SPECIAL_FILES:
51
- special_path = path / special_file
52
- if special_path.exists() and special_path.resolve() not in processed_files:
53
- special_found.append(special_file)
54
- processed_files.add(special_path.resolve())
55
- if special_found:
56
- file_items[-1] = f"[blue]•[/blue] {relative_path}/ [cyan]({', '.join(special_found)})[/cyan]"
57
- for special_file in special_found:
58
- special_path = path / special_file
59
- try:
60
- relative_path = special_path.relative_to(relative_base)
61
- file_content = special_path.read_text(encoding='utf-8')
62
- content_parts.append(f"<file>\n<path>{relative_path}</path>\n<content>\n{file_content}\n</content>\n</file>")
63
- except UnicodeDecodeError:
64
- skipped_files.append(str(relative_path))
65
- console.print(f"[yellow]Warning: Skipping file due to encoding issues: {relative_path}[/yellow]")
66
-
67
- for item in path.iterdir():
68
- # Skip if matches gitignore patterns
69
- if gitignore_spec:
70
- rel_path = str(item.relative_to(workdir))
71
- if gitignore_spec.match_file(rel_path):
72
- continue
73
- if item.resolve() not in processed_files: # Skip if already processed
74
- scan_path(item, level+1)
75
-
76
- else:
77
- resolved_path = path.resolve()
78
- if resolved_path in processed_files: # Skip if already processed
79
- return
80
-
81
- processed_files.add(resolved_path)
82
- relative_path = path.relative_to(relative_base)
83
- # check if file is binary
84
- try:
85
- if path.is_file() and path.read_bytes().find(b'\x00') != -1:
86
- console.print(f"[red]Skipped binary file found: {relative_path}[/red]")
87
- return
88
- file_content = path.read_text(encoding='utf-8')
89
- content_parts.append(f"<file>\n<path>{relative_path}</path>\n<content>\n{file_content}\n</content>\n</file>")
90
- file_items.append(f"[cyan]•[/cyan] {relative_path}")
91
- except UnicodeDecodeError:
92
- skipped_files.append(str(relative_path))
93
- console.print(f"[yellow]Warning: Skipping file due to encoding issues: {relative_path}[/yellow]")
94
-
95
- for path in paths:
96
- scan_path(path, 0)
97
-
98
- if skipped_files and config.verbose:
99
- console.print("\n[yellow]Files skipped due to encoding issues:[/yellow]")
100
- for file in skipped_files:
101
- console.print(f" • {file}")
102
-
103
- return content_parts, file_items
104
-
105
- def collect_files_content(paths: List[Path], workdir: Path = None) -> str:
106
- """Collect content from all files in XML format"""
107
- console = Console()
108
- content_parts, file_items = _scan_paths(paths, workdir)
109
-
110
- if file_items and config.verbose:
111
- console.print("\n[bold blue]Contents being analyzed:[/bold blue]")
112
- console.print(Columns(file_items, padding=(0, 4), expand=True))
113
-
114
- if config.verbose:
115
- for part in content_parts:
116
- if part.startswith('<file>'):
117
- # Extract filename from XML content
118
- path_start = part.find('<path>') + 6
119
- path_end = part.find('</path>')
120
- if path_start > 5 and path_end > path_start:
121
- filepath = part[path_start:path_end]
122
- console.print(f"[dim]Adding content from:[/dim] {filepath}")
123
-
124
- return "\n".join(content_parts)
125
-
126
-
127
- def preview_scan(paths: List[Path], workdir: Path = None) -> None:
128
- """Preview what files and directories would be scanned"""
129
- console = Console()
130
- _, file_items = _scan_paths(paths, workdir)
131
-
132
- # Display working directory status
133
- console.print("\n[bold blue]Analysis Paths:[/bold blue]")
134
- console.print(f"[cyan]Working Directory:[/cyan] {workdir.absolute()}")
135
-
136
- # Show if working directory is being scanned
137
- is_workdir_scanned = any(p.resolve() == workdir.resolve() for p in paths)
138
- if is_workdir_scanned:
139
- console.print("[green]✓ Working directory will be scanned[/green]")
140
- else:
141
- console.print("[yellow]! Working directory will not be scanned[/yellow]")
142
-
143
- # Show included paths relative to working directory
144
- if len(paths) > (1 if is_workdir_scanned else 0):
145
- console.print("\n[cyan]Additional Included Paths:[/cyan]")
146
- for path in paths:
147
- if path.resolve() != workdir.resolve():
148
- try:
149
- rel_path = path.relative_to(workdir)
150
- console.print(f" • ./{rel_path}")
151
- except ValueError:
152
- # Path is outside working directory
153
- console.print(f" • {path.absolute()}")
154
-
155
- console.print("\n[bold blue]Files that will be analyzed:[/bold blue]")
156
- console.print(Columns(file_items, padding=(0, 4), expand=True))
157
-
158
- def is_dir_empty(path: Path) -> bool:
159
- """Check if directory is empty, ignoring hidden files"""
160
- return not any(item for item in path.iterdir() if not item.name.startswith('.'))
161
-
162
- def show_content_stats(content: str) -> None:
163
- if not content:
164
- return
165
-
166
- dir_counts = defaultdict(int)
167
- for line in content.split('\n'):
168
- if line.startswith('<path>'):
169
- path = Path(line.replace('<path>', '').replace('</path>', '').strip())
170
- dir_counts[str(path.parent)] += 1
171
-
172
- console = Console()
173
- stats = [f"{directory} ({count} files)" for directory, count in dir_counts.items()]
174
- columns = Columns(stats, equal=True, expand=True)
175
- panel = Panel(columns, title="Work Context")
176
- console.print(panel)
@@ -1,26 +0,0 @@
1
- import pytest
2
- from pathlib import Path
3
- from janito.fileparser import validate_file_path, validate_file_content
4
-
5
- def test_validate_file_path():
6
- # Valid paths
7
- assert validate_file_path(Path("test.py")) == (True, "")
8
- assert validate_file_path(Path("folder/test.py")) == (True, "")
9
-
10
- # Invalid paths
11
- assert validate_file_path(Path("/absolute/path.py"))[0] == False
12
- assert validate_file_path(Path("../escape.py"))[0] == False
13
- assert validate_file_path(Path("test?.py"))[0] == False
14
- assert validate_file_path(Path("test*.py"))[0] == False
15
-
16
- def test_validate_file_content():
17
- # Valid content
18
- assert validate_file_content("print('hello')") == (True, "")
19
- assert validate_file_content("# Empty file with comment\n") == (True, "")
20
-
21
- # Invalid content
22
- assert validate_file_content("")[0] == False
23
-
24
- # Test large content
25
- large_content = "x" * (1024 * 1024 + 1) # Slightly over 1MB
26
- assert validate_file_content(large_content)[0] == False
@@ -1,146 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: janito
3
- Version: 0.5.0
4
- Summary: A CLI tool for software development tasks powered by AI
5
- Project-URL: Homepage, https://github.com/joaompinto/janito
6
- Project-URL: Repository, https://github.com/joaompinto/janito.git
7
- Author-email: João Pinto <lamego.pinto@gmail.com>
8
- License: MIT
9
- Classifier: Development Status :: 4 - Beta
10
- Classifier: Environment :: Console
11
- Classifier: Intended Audience :: Developers
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Programming Language :: Python :: 3.8
14
- Classifier: Programming Language :: Python :: 3.9
15
- Classifier: Programming Language :: Python :: 3.10
16
- Classifier: Topic :: Software Development
17
- Requires-Python: >=3.8
18
- Requires-Dist: anthropic
19
- Requires-Dist: pathspec
20
- Requires-Dist: rich
21
- Requires-Dist: tomli
22
- Requires-Dist: typer
23
- Description-Content-Type: text/markdown
24
-
25
- # 🤖 Janito CLI
26
-
27
- A CLI tool for software development tasks powered by AI. Janito is your friendly AI-powered software development buddy that helps with coding tasks like refactoring, documentation updates, and code optimization.
28
-
29
- ## 📥 Installation
30
-
31
- 1. Install using pip:
32
- ```bash
33
- pip install janito
34
- ```
35
-
36
- 2. Verify installation:
37
- ```bash
38
- janito --version
39
- ```
40
-
41
- ## ⚙️ Setup
42
-
43
- 1. Get your Anthropic API key from [Anthropic's website](https://www.anthropic.com/)
44
-
45
- 2. Set your API key:
46
- ```bash
47
- # Linux/macOS
48
- export ANTHROPIC_API_KEY='your-api-key-here'
49
-
50
- # Windows (Command Prompt)
51
- set ANTHROPIC_API_KEY=your-api-key-here
52
-
53
- # Windows (PowerShell)
54
- $env:ANTHROPIC_API_KEY='your-api-key-here'
55
- ```
56
-
57
- 3. (Optional) Configure default test command:
58
- ```bash
59
- export JANITO_TEST_CMD='pytest' # or your preferred test command
60
- ```
61
-
62
- ## 🚀 Quick Start
63
-
64
- ### Basic Usage
65
-
66
- ```bash
67
- # Add docstrings to your code
68
- janito "add docstrings to this file"
69
-
70
- # Optimize a function
71
- janito "optimize the main function"
72
-
73
- # Get code explanations
74
- janito --ask "explain this code"
75
- ```
76
-
77
- ### Common Scenarios
78
-
79
- 1. **Code Refactoring**
80
- ```bash
81
- # Refactor with test validation
82
- janito "refactor this code to use list comprehension" --test "pytest"
83
-
84
- # Refactor specific directory
85
- janito "update imports" -i ./src
86
- ```
87
-
88
- 2. **Documentation Updates**
89
- ```bash
90
- # Add or update docstrings
91
- janito "add type hints and docstrings"
92
-
93
- # Generate README
94
- janito "create a README for this project"
95
- ```
96
-
97
- 3. **Code Analysis**
98
- ```bash
99
- # Get code explanations
100
- janito --ask "what does this function do?"
101
-
102
- # Find potential improvements
103
- janito --ask "suggest optimizations for this code"
104
- ```
105
-
106
- ## 🛠️ Command Reference
107
-
108
- ### Syntax
109
- ```bash
110
- janito [OPTIONS] [REQUEST]
111
- ```
112
-
113
- ### Key Options
114
-
115
- | Option | Description |
116
- |--------|-------------|
117
- | `REQUEST` | The AI request/instruction (in quotes) |
118
- | `-w, --working-dir PATH` | Working directory [default: current] |
119
- | `-i, --include PATH` | Include directory int the working context (can be multiple)|
120
- | `--ask QUESTION` | Ask questions without making changes |
121
- | `--test COMMAND` | Run tests before applying changes |
122
- | `--debug` | Enable debug logging |
123
- | `--verbose` | Enable verbose mode |
124
- | `--version` | Show version information |
125
- | `--help` | Show help message |
126
-
127
- ## 🔑 Key Features
128
-
129
- - 🤖 AI-powered code analysis and modifications
130
- - 💻 Interactive console mode
131
- - ✅ Syntax validation for Python files
132
- - 👀 Change preview and confirmation
133
- - 🧪 Test command execution
134
- - 📜 Change history tracking
135
-
136
- ## 📚 Additional Information
137
-
138
- - Requires Python 3.8+
139
- - Changes are backed up in `.janito/changes_history/`
140
- - Environment variables:
141
- - `ANTHROPIC_API_KEY`: Required for API access
142
- - `JANITO_TEST_CMD`: Default test command (optional)
143
-
144
- ## 📄 License
145
-
146
- MIT License - see [LICENSE](LICENSE) file for details.
@@ -1,45 +0,0 @@
1
- janito/__init__.py,sha256=T1hTuIOJgEUjXNHplUuMZIgG_QxC1RH2ZcBe6WJ1XBE,1099
2
- janito/__main__.py,sha256=ogcCBQ2YHkQhdhrXF7OV-DthLiL-Zw24XtRRYscT2Yo,2018
3
- janito/_contextparser.py,sha256=iDX6nlqUQr-lj7lkEI4B6jHLci_Kxl-XWOaEiAQtVxA,4531
4
- janito/changehistory.py,sha256=4Mu60og1pySlyfB36aqHnNKyH0yuSj-5rvBjmmvKGYw,1510
5
- janito/common.py,sha256=imIwx0FCDe7p71ze9TBvn_W0Qz99Am3X5U9eHYd9vws,790
6
- janito/config.py,sha256=ocg0lyab9ysgczKaqJTAtv0ZRa2VDMwclTJBgps7Vxw,1171
7
- janito/fileparser.py,sha256=rJEme9QWbtnsjs9KuO3YI7B499DnfedWtzBONXqrjfU,12925
8
- janito/prompts.py,sha256=M8IveFkG3fgLe87_9kTNdWAVkqmsD0T4eP6VmOqHAOQ,2607
9
- janito/qa.py,sha256=MSzu9yvLCwXr9sKylTXtMfTy_2fRfPl3CU2NXf0OrS4,1977
10
- janito/review.py,sha256=5Oc6BfxMGNmKbIeDP5_EiAKUDeQwVOD0YL7iqfgJLRE,471
11
- janito/scan.py,sha256=QBXu64t8CjjJhiFdO-0npwdSPys9IX1oOOOyh1cGVIE,7678
12
- janito/version.py,sha256=ylfPwGtdY8dEOFJ-DB9gKUQLggqRCvoLxhpnwjzCM94,739
13
- janito/agents/__init__.py,sha256=VPBXIh526D11NrCSnuXUerYT7AI3rynp2klCgz94tPk,648
14
- janito/agents/agent.py,sha256=3uGiUrvj9oCW6_oK-oMQQJ77K8jZFv7mAdXlIG1dxNY,751
15
- janito/agents/claudeai.py,sha256=bl1MeALicf6arX_m9GmtAj0i3UoUiTbbXytVjLam2S8,2395
16
- janito/agents/openai.py,sha256=tNtlzFJMWFv38Z62opR23u6xXlZ9L4xX_mf2f3wjrLU,2082
17
- janito/agents/test.py,sha256=xoN1q9DUSYpUbnvTP1qZsEfxYrZfocJlt9DkIuMDvvY,1552
18
- janito/analysis/__init__.py,sha256=QVhIoZdOc4eYhQ9ZRoZZiwowUaa-PQ0_7HV_cx4eOZU,734
19
- janito/analysis/display.py,sha256=714423TxelieAyBe0M5A78i99qj_VfggZUWRbk2owzU,5204
20
- janito/analysis/options.py,sha256=tgsLZOtNy35l4v4F6p_adGk3CrWhrDN0Ba_tw4Zzj5Q,3852
21
- janito/analysis/prompts.py,sha256=7NI7XyL6gUeJWTfVP_X0ohtSnYb6gpu4Thy5kxzoeD8,2454
22
- janito/change/__init__.py,sha256=ElyiGt6KmwufQouir-0l0ZtxNZdeLWTFRc4Vbg0RW3s,467
23
- janito/change/applier.py,sha256=GXs0DRfb48WNoSyAH0uETjpzzFLvmUZGkb6VydKzazk,11601
24
- janito/change/content.py,sha256=R8lbOFF2ANV_NF3S6zCV60-Q7hGFWiS-zmJBgu-r5SU,2475
25
- janito/change/indentation.py,sha256=qvsGX9ZPm5cRftXJSKSVbK9-Po_95HCAc7sG98BxhIY,1191
26
- janito/change/position.py,sha256=Nlkg0sGUvqYwtKA19ne1kT3ixiVYKUcy_40Cdr-gfl8,6385
27
- janito/changeviewer/__init__.py,sha256=5kR3fsAYSgnA0Hlty0fMC6392aSK7WifH2ZIW-INjBc,298
28
- janito/changeviewer/diff.py,sha256=2nW1Yzu7rzzIsuHWg-t2EJfsoVdbRaRJk3ewQBjQdxY,1117
29
- janito/changeviewer/panels.py,sha256=F1yWUd6Vh535rV20NnFrVh6uvpc3w5CDBSNQUf_vOC8,9426
30
- janito/changeviewer/styling.py,sha256=qv7DVfu57Qy93XUWIWdyqZWhgcfm-BaJVPslSuch05s,2461
31
- janito/changeviewer/themes.py,sha256=BWa4l82fNM0pj01UYK9q_C7t_AqTwNbR8i0-F4I7KI8,1593
32
- janito/cli/__init__.py,sha256=3gyMSaEAH2N4mXfZTLsHXKxXDxdhlYUeAPYQuhnOVBE,77
33
- janito/cli/commands.py,sha256=6vPT60oT-1jJd_qdy-Si_pcf7yMCGmwpvQ43FZNJjUs,2001
34
- janito/cli/functions.py,sha256=5Nn4muPv1KrInhcernByQqn_T0q2bCxPeDA1BoPw4K8,11399
35
- janito/cli/registry.py,sha256=R1sI45YonxjMSLhAle7Dt18X_devrMsLt0ljb-rNza4,690
36
- janito/console/__init__.py,sha256=0zxlJR88ESfuXtyzARnWNKcZ1rTyWLZwzXrfDQ7NHyw,77
37
- janito/console/commands.py,sha256=kuI2w1LfEw0kbF_vOAYVENoMQYC42fXmDFZgxVKJKo8,3422
38
- janito/console/core.py,sha256=DTAP_bhw_DTklUyPbGdjSzllUBMg7jXW0SklXkRNMI8,2264
39
- janito/console/display.py,sha256=VNyHGHA_MG-dLPTCylgOKgHAl0muwhmsvg3nXFU-OZo,5380
40
- janito/tests/test_fileparser.py,sha256=20CfwfnFtVm3_qU11qRAdcBZQXaLlkcHgbqWDOeazj4,997
41
- janito-0.5.0.dist-info/METADATA,sha256=Jq4fJLGNs-4O8IOB2iy_8JrszlWbFzOmwrZRjQxIs_Y,3659
42
- janito-0.5.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
43
- janito-0.5.0.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
44
- janito-0.5.0.dist-info/licenses/LICENSE,sha256=xLIUXRPjtsgQml2zD1Pn4LpgiyZ49raw6jZDlO_gZdo,1062
45
- janito-0.5.0.dist-info/RECORD,,