Open-AutoTools 0.0.3rc5__py3-none-any.whl → 0.0.4rc1__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.
- autotools/autocaps/commands.py +3 -7
- autotools/autocaps/core.py +5 -4
- autotools/autoip/commands.py +6 -11
- autotools/autoip/core.py +151 -200
- autotools/autolower/commands.py +3 -7
- autotools/autolower/core.py +4 -3
- autotools/autopassword/commands.py +27 -33
- autotools/autopassword/core.py +32 -73
- autotools/autotest/__init__.py +2 -0
- autotools/autotest/commands.py +205 -0
- autotools/cli.py +123 -62
- autotools/utils/commands.py +13 -0
- autotools/utils/loading.py +14 -6
- autotools/utils/performance.py +392 -0
- autotools/utils/updates.py +30 -22
- autotools/utils/version.py +69 -63
- open_autotools-0.0.4rc1.dist-info/METADATA +103 -0
- open_autotools-0.0.4rc1.dist-info/RECORD +28 -0
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info}/WHEEL +1 -1
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info}/entry_points.txt +0 -3
- Open_AutoTools-0.0.3rc5.dist-info/METADATA +0 -317
- Open_AutoTools-0.0.3rc5.dist-info/RECORD +0 -44
- autotools/autocaps/tests/__init__.py +0 -1
- autotools/autocaps/tests/test_autocaps_core.py +0 -45
- autotools/autocaps/tests/test_autocaps_integration.py +0 -46
- autotools/autodownload/__init__.py +0 -0
- autotools/autodownload/commands.py +0 -38
- autotools/autodownload/core.py +0 -433
- autotools/autoip/tests/__init__.py +0 -1
- autotools/autoip/tests/test_autoip_core.py +0 -72
- autotools/autoip/tests/test_autoip_integration.py +0 -92
- autotools/autolower/tests/__init__.py +0 -1
- autotools/autolower/tests/test_autolower_core.py +0 -45
- autotools/autolower/tests/test_autolower_integration.py +0 -46
- autotools/autospell/__init__.py +0 -3
- autotools/autospell/commands.py +0 -123
- autotools/autospell/core.py +0 -222
- autotools/autotranslate/__init__.py +0 -3
- autotools/autotranslate/commands.py +0 -42
- autotools/autotranslate/core.py +0 -52
- autotools/test/__init__.py +0 -3
- autotools/test/commands.py +0 -118
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info/licenses}/LICENSE +0 -0
- {Open_AutoTools-0.0.3rc5.dist-info → open_autotools-0.0.4rc1.dist-info}/top_level.txt +0 -0
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from click.testing import CliRunner
|
|
3
|
-
from autotools.cli import autolower
|
|
4
|
-
|
|
5
|
-
# INTEGRATION TESTS
|
|
6
|
-
|
|
7
|
-
# TEST FOR BASIC CLI FUNCTIONALITY
|
|
8
|
-
def test_autolower_cli_basic():
|
|
9
|
-
"""TEST BASIC CLI FUNCTIONALITY"""
|
|
10
|
-
runner = CliRunner()
|
|
11
|
-
result = runner.invoke(autolower, ["HELLO WORLD"])
|
|
12
|
-
assert result.exit_code == 0
|
|
13
|
-
assert "hello world" in result.output
|
|
14
|
-
|
|
15
|
-
# TEST FOR EMPTY INPUT
|
|
16
|
-
def test_autolower_cli_empty():
|
|
17
|
-
"""TEST CLI WITH EMPTY INPUT"""
|
|
18
|
-
runner = CliRunner()
|
|
19
|
-
result = runner.invoke(autolower, [""])
|
|
20
|
-
assert result.exit_code == 0
|
|
21
|
-
assert "" in result.output
|
|
22
|
-
|
|
23
|
-
# TEST FOR SPECIAL CHARACTERS
|
|
24
|
-
def test_autolower_cli_special_chars():
|
|
25
|
-
"""TEST CLI WITH SPECIAL CHARACTERS"""
|
|
26
|
-
runner = CliRunner()
|
|
27
|
-
result = runner.invoke(autolower, ["HELLO@WORLD.COM"])
|
|
28
|
-
assert result.exit_code == 0
|
|
29
|
-
assert "hello@world.com" in result.output
|
|
30
|
-
|
|
31
|
-
# TEST FOR UNICODE CHARACTERS
|
|
32
|
-
def test_autolower_cli_unicode():
|
|
33
|
-
"""TEST CLI WITH UNICODE CHARACTERS"""
|
|
34
|
-
runner = CliRunner()
|
|
35
|
-
result = runner.invoke(autolower, ["HÉLLO WÖRLD"])
|
|
36
|
-
assert result.exit_code == 0
|
|
37
|
-
assert "héllo wörld" in result.output
|
|
38
|
-
|
|
39
|
-
# TEST FOR MULTIPLE ARGUMENTS
|
|
40
|
-
def test_autolower_cli_multiple_args():
|
|
41
|
-
"""TEST CLI WITH MULTIPLE ARGUMENTS"""
|
|
42
|
-
runner = CliRunner()
|
|
43
|
-
result = runner.invoke(autolower, ["HELLO", "WORLD"])
|
|
44
|
-
assert result.exit_code == 0
|
|
45
|
-
# SHOULD ONLY PROCESS FIRST ARGUMENT
|
|
46
|
-
assert "hello" in result.output
|
autotools/autospell/__init__.py
DELETED
autotools/autospell/commands.py
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
import json as json_module
|
|
3
|
-
from .core import SpellChecker
|
|
4
|
-
from ..utils.loading import LoadingAnimation
|
|
5
|
-
from ..utils.updates import check_for_updates
|
|
6
|
-
|
|
7
|
-
@click.command()
|
|
8
|
-
@click.argument('texts', nargs=-1)
|
|
9
|
-
@click.option('--lang', '-l', default='auto', help='Language code (auto for detection)')
|
|
10
|
-
@click.option('--fix', '-f', is_flag=True, help='Auto-fix text and copy to clipboard')
|
|
11
|
-
@click.option('--copy', '-c', is_flag=True, help='Copy result to clipboard')
|
|
12
|
-
@click.option('--list-languages', is_flag=True, help='List supported languages')
|
|
13
|
-
@click.option('--json', '-j', is_flag=True, help='Output results as JSON')
|
|
14
|
-
@click.option('--ignore', '-i', multiple=True,
|
|
15
|
-
type=click.Choice(['spelling', 'grammar', 'style', 'punctuation']),
|
|
16
|
-
help='Error types to ignore')
|
|
17
|
-
@click.option('--interactive', '-n', is_flag=True,
|
|
18
|
-
help='Interactive mode - confirm each correction')
|
|
19
|
-
@click.option('--output', '-o', type=click.Path(),
|
|
20
|
-
help='Save corrections to file')
|
|
21
|
-
def autospell(texts: tuple, lang: str, fix: bool, copy: bool, list_languages: bool,
|
|
22
|
-
json: bool, ignore: tuple, interactive: bool, output: str):
|
|
23
|
-
"""Check and fix text for spelling, grammar, style, and punctuation errors.
|
|
24
|
-
|
|
25
|
-
Provides comprehensive text analysis with support for multiple languages,
|
|
26
|
-
interactive corrections, and various output formats (text/JSON).
|
|
27
|
-
Can ignore specific error types: spelling, grammar, style, or punctuation."""
|
|
28
|
-
checker = SpellChecker()
|
|
29
|
-
|
|
30
|
-
# LIST ALL SUPPORTED LANGUAGES
|
|
31
|
-
if list_languages:
|
|
32
|
-
with LoadingAnimation():
|
|
33
|
-
languages = checker.get_supported_languages()
|
|
34
|
-
if json:
|
|
35
|
-
result = {'languages': languages}
|
|
36
|
-
click.echo(json_module.dumps(result, indent=2))
|
|
37
|
-
else:
|
|
38
|
-
click.echo("\nSupported Languages:")
|
|
39
|
-
for lang in languages:
|
|
40
|
-
click.echo(f"{lang['code']:<8} {lang['name']}")
|
|
41
|
-
return
|
|
42
|
-
|
|
43
|
-
# --CHECK AND FIX SPELLING/GRAMMAR IN TEXT
|
|
44
|
-
for text in texts:
|
|
45
|
-
if not text:
|
|
46
|
-
click.echo("Error: Please provide text to check")
|
|
47
|
-
continue
|
|
48
|
-
|
|
49
|
-
# --FIX OPTION: SPELLING/GRAMMAR IN TEXT
|
|
50
|
-
if fix:
|
|
51
|
-
# CORRECT TEXT WITH SPELL CHECKER
|
|
52
|
-
with LoadingAnimation():
|
|
53
|
-
corrected = checker.fix_text(text, lang, copy_to_clipboard=True,
|
|
54
|
-
ignore=ignore, interactive=interactive)
|
|
55
|
-
result = {'corrected_text': corrected}
|
|
56
|
-
|
|
57
|
-
# OUTPUT RESULTS AS JSON
|
|
58
|
-
if json:
|
|
59
|
-
click.echo(json_module.dumps(result, indent=2))
|
|
60
|
-
else:
|
|
61
|
-
# LANGUAGE INFORMATION
|
|
62
|
-
with LoadingAnimation():
|
|
63
|
-
check_result = checker.check_text(text, lang)
|
|
64
|
-
lang_info = check_result['language']
|
|
65
|
-
click.echo(f"\nLanguage detected: {lang_info['name']} ({lang_info['code']})")
|
|
66
|
-
click.echo(f"Confidence: {lang_info['confidence']:.2%}")
|
|
67
|
-
click.echo("\nCorrected text (copied to clipboard):")
|
|
68
|
-
click.echo(corrected)
|
|
69
|
-
|
|
70
|
-
# SAVE CORRECTIONS TO FILE
|
|
71
|
-
if output:
|
|
72
|
-
with open(output, 'w', encoding='utf-8') as f:
|
|
73
|
-
if json:
|
|
74
|
-
json_module.dump(result, f, indent=2)
|
|
75
|
-
else:
|
|
76
|
-
f.write(corrected)
|
|
77
|
-
else:
|
|
78
|
-
# CHECK SPELLING/GRAMMAR IN TEXT
|
|
79
|
-
with LoadingAnimation():
|
|
80
|
-
check_result = checker.check_text(text, lang)
|
|
81
|
-
|
|
82
|
-
# OUTPUT RESULTS AS JSON
|
|
83
|
-
if json:
|
|
84
|
-
click.echo(json_module.dumps(check_result, indent=2))
|
|
85
|
-
else:
|
|
86
|
-
lang_info = check_result['language']
|
|
87
|
-
click.echo(f"\nLanguage detected: {lang_info['name']} ({lang_info['code']})")
|
|
88
|
-
click.echo(f"Confidence: {lang_info['confidence']:.2%}")
|
|
89
|
-
click.echo(f"Total errors found: {check_result['statistics']['total_errors']}")
|
|
90
|
-
|
|
91
|
-
# CORRECTIONS SUGGESTED
|
|
92
|
-
if check_result['corrections']:
|
|
93
|
-
click.echo("\nCorrections suggested:")
|
|
94
|
-
for i, corr in enumerate(check_result['corrections'], 1):
|
|
95
|
-
click.echo(f"\n{i}. [{corr['severity'].upper()}] {corr['message']}")
|
|
96
|
-
click.echo(f" Context: {corr['context']}")
|
|
97
|
-
if corr['replacements']:
|
|
98
|
-
click.echo(f" Suggestions: {', '.join(corr['replacements'][:3])}")
|
|
99
|
-
|
|
100
|
-
# SAVE CHECK RESULT TO FILE
|
|
101
|
-
if output:
|
|
102
|
-
with open(output, 'w', encoding='utf-8') as f:
|
|
103
|
-
if json:
|
|
104
|
-
json_module.dump(check_result, f, indent=2)
|
|
105
|
-
else:
|
|
106
|
-
# WRITE A HUMAN-READABLE REPORT
|
|
107
|
-
f.write(f"Language: {lang_info['name']} ({lang_info['code']})\n")
|
|
108
|
-
f.write(f"Confidence: {lang_info['confidence']:.2%}\n")
|
|
109
|
-
f.write(f"Total errors: {check_result['statistics']['total_errors']}\n\n")
|
|
110
|
-
|
|
111
|
-
# CORRECTIONS SUGGESTED
|
|
112
|
-
if check_result['corrections']:
|
|
113
|
-
f.write("Corrections suggested:\n")
|
|
114
|
-
for i, corr in enumerate(check_result['corrections'], 1):
|
|
115
|
-
f.write(f"\n{i}. [{corr['severity'].upper()}] {corr['message']}\n")
|
|
116
|
-
f.write(f" Context: {corr['context']}\n")
|
|
117
|
-
if corr['replacements']:
|
|
118
|
-
f.write(f" Suggestions: {', '.join(corr['replacements'][:3])}\n")
|
|
119
|
-
|
|
120
|
-
# UPDATE CHECK AT THE END
|
|
121
|
-
update_msg = check_for_updates()
|
|
122
|
-
if update_msg:
|
|
123
|
-
click.echo(update_msg)
|
autotools/autospell/core.py
DELETED
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
import language_tool_python
|
|
2
|
-
import spacy
|
|
3
|
-
from typing import List, Dict, Optional
|
|
4
|
-
import pyperclip
|
|
5
|
-
import requests
|
|
6
|
-
from langdetect import detect, detect_langs
|
|
7
|
-
|
|
8
|
-
class SpellChecker:
|
|
9
|
-
def __init__(self):
|
|
10
|
-
# INITIALIZE LANGUAGE TOOL
|
|
11
|
-
self.tool = language_tool_python.LanguageTool('auto')
|
|
12
|
-
|
|
13
|
-
# CACHE FOR SPACY MODELS
|
|
14
|
-
self.nlp_models = {}
|
|
15
|
-
|
|
16
|
-
# LOAD SPACY MODEL FOR GIVEN LANGUAGE
|
|
17
|
-
def _load_spacy_model(self, lang_code: str) -> Optional[spacy.language.Language]:
|
|
18
|
-
"""LOAD SPACY MODEL FOR GIVEN LANGUAGE"""
|
|
19
|
-
try:
|
|
20
|
-
if lang_code not in self.nlp_models:
|
|
21
|
-
# GET ALL INSTALLED MODELS FOR THIS LANGUAGE
|
|
22
|
-
available_models = [
|
|
23
|
-
model for model in spacy.util.get_installed_models()
|
|
24
|
-
if model.startswith(lang_code)
|
|
25
|
-
]
|
|
26
|
-
|
|
27
|
-
if not available_models:
|
|
28
|
-
# TRY TO CREATE A BLANK MODEL IF NO TRAINED MODELS
|
|
29
|
-
self.nlp_models[lang_code] = spacy.blank(lang_code)
|
|
30
|
-
else:
|
|
31
|
-
# USE MOST COMPREHENSIVE MODEL (USUALLY ENDS WITH 'lg' OR 'trf')
|
|
32
|
-
preferred_model = None
|
|
33
|
-
for suffix in ['trf', 'lg', 'md', 'sm']:
|
|
34
|
-
for model in available_models:
|
|
35
|
-
if model.endswith(suffix):
|
|
36
|
-
preferred_model = model
|
|
37
|
-
break
|
|
38
|
-
if preferred_model:
|
|
39
|
-
break
|
|
40
|
-
|
|
41
|
-
# IF NO PREFERRED MODEL, USE FIRST AVAILABLE MODEL
|
|
42
|
-
if not preferred_model:
|
|
43
|
-
preferred_model = available_models[0]
|
|
44
|
-
|
|
45
|
-
self.nlp_models[lang_code] = spacy.load(preferred_model) # LOAD PREFERRED MODEL
|
|
46
|
-
|
|
47
|
-
return self.nlp_models.get(lang_code) # RETURN LOADED MODEL
|
|
48
|
-
except:
|
|
49
|
-
return None
|
|
50
|
-
|
|
51
|
-
# CHECK TEXT FOR SPELLING AND GRAMMAR ERRORS
|
|
52
|
-
def check_text(self, text: str, lang: str = 'auto') -> Dict:
|
|
53
|
-
"""CHECK TEXT FOR SPELLING AND GRAMMAR ERRORS
|
|
54
|
-
|
|
55
|
-
ARGS:
|
|
56
|
-
text: Text to check
|
|
57
|
-
lang: Language code (auto for automatic detection)
|
|
58
|
-
|
|
59
|
-
RETURNS:
|
|
60
|
-
Dict with corrections and statistics
|
|
61
|
-
"""
|
|
62
|
-
# DETECT LANGUAGE CONFIDENCE
|
|
63
|
-
if lang == 'auto':
|
|
64
|
-
try:
|
|
65
|
-
lang_scores = detect_langs(text)
|
|
66
|
-
lang = lang_scores[0].lang
|
|
67
|
-
confidence = lang_scores[0].prob
|
|
68
|
-
except:
|
|
69
|
-
confidence = 0
|
|
70
|
-
else:
|
|
71
|
-
confidence = 1.0
|
|
72
|
-
|
|
73
|
-
# SET LANGUAGE
|
|
74
|
-
if lang != 'auto':
|
|
75
|
-
self.tool.language = lang
|
|
76
|
-
|
|
77
|
-
# GET MATCHES
|
|
78
|
-
matches = self.tool.check(text)
|
|
79
|
-
|
|
80
|
-
# PREPARE CORRECTIONS WITH SEVERITY LEVELS
|
|
81
|
-
corrections = []
|
|
82
|
-
for match in matches:
|
|
83
|
-
severity = self._get_error_severity(match)
|
|
84
|
-
correction = {
|
|
85
|
-
'message': match.message,
|
|
86
|
-
'context': match.context,
|
|
87
|
-
'offset': match.offset,
|
|
88
|
-
'length': match.errorLength,
|
|
89
|
-
'category': match.category,
|
|
90
|
-
'rule_id': match.ruleId,
|
|
91
|
-
'replacements': match.replacements,
|
|
92
|
-
'severity': severity
|
|
93
|
-
}
|
|
94
|
-
corrections.append(correction)
|
|
95
|
-
|
|
96
|
-
# GET DETAILED STATISTICS
|
|
97
|
-
stats = self._get_detailed_stats(corrections)
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
'corrections': corrections,
|
|
101
|
-
'statistics': stats,
|
|
102
|
-
'language': {
|
|
103
|
-
'code': lang,
|
|
104
|
-
'name': lang.upper(),
|
|
105
|
-
'confidence': confidence
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
# DETERMINE ERROR SEVERITY LEVEL
|
|
110
|
-
def _get_error_severity(self, match) -> str:
|
|
111
|
-
"""DETERMINE ERROR SEVERITY LEVEL"""
|
|
112
|
-
if 'TYPO' in match.ruleId or 'SPELLING' in match.ruleId:
|
|
113
|
-
return 'high'
|
|
114
|
-
elif 'GRAMMAR' in match.ruleId:
|
|
115
|
-
return 'medium'
|
|
116
|
-
else:
|
|
117
|
-
return 'low'
|
|
118
|
-
|
|
119
|
-
# GET DETAILED ERROR STATISTICS
|
|
120
|
-
def _get_detailed_stats(self, corrections: List[Dict]) -> Dict:
|
|
121
|
-
"""GET DETAILED ERROR STATISTICS"""
|
|
122
|
-
stats = {
|
|
123
|
-
'total_errors': len(corrections),
|
|
124
|
-
'categories': {},
|
|
125
|
-
'severity': {
|
|
126
|
-
'high': 0,
|
|
127
|
-
'medium': 0,
|
|
128
|
-
'low': 0
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
# COUNT ERRORS BY CATEGORY AND SEVERITY
|
|
133
|
-
for corr in corrections:
|
|
134
|
-
# COUNT BY CATEGORY
|
|
135
|
-
cat = corr['category']
|
|
136
|
-
stats['categories'][cat] = stats['categories'].get(cat, 0) + 1
|
|
137
|
-
|
|
138
|
-
# COUNT BY SEVERITY
|
|
139
|
-
stats['severity'][corr['severity']] += 1
|
|
140
|
-
|
|
141
|
-
return stats
|
|
142
|
-
|
|
143
|
-
# FIX TEXT AUTOMATICALLY
|
|
144
|
-
def fix_text(self, text: str, lang: str = 'auto', copy_to_clipboard: bool = False,
|
|
145
|
-
ignore: list = None, interactive: bool = False) -> str:
|
|
146
|
-
"""FIX TEXT AUTOMATICALLY"""
|
|
147
|
-
if lang != 'auto':
|
|
148
|
-
self.tool.language = lang
|
|
149
|
-
|
|
150
|
-
if interactive:
|
|
151
|
-
# GET ALL CORRECTIONS
|
|
152
|
-
matches = self.tool.check(text)
|
|
153
|
-
corrected = text
|
|
154
|
-
|
|
155
|
-
# ASK FOR EACH CORRECTION
|
|
156
|
-
for match in matches:
|
|
157
|
-
if ignore and any(t in match.ruleId.lower() for t in ignore):
|
|
158
|
-
continue
|
|
159
|
-
|
|
160
|
-
print(f"\nError: {match.message}")
|
|
161
|
-
print(f"Context: {match.context}")
|
|
162
|
-
if match.replacements:
|
|
163
|
-
print("Suggestions:")
|
|
164
|
-
for i, sugg in enumerate(match.replacements[:3], 1):
|
|
165
|
-
print(f"{i}. {sugg}")
|
|
166
|
-
|
|
167
|
-
# ASK FOR EACH CORRECTION
|
|
168
|
-
choice = input("\nApply correction? (1-3/n): ").lower()
|
|
169
|
-
if choice.isdigit() and 1 <= int(choice) <= len(match.replacements[:3]):
|
|
170
|
-
replacement = match.replacements[int(choice)-1]
|
|
171
|
-
corrected = corrected[:match.offset] + replacement + corrected[match.offset + match.errorLength:]
|
|
172
|
-
else:
|
|
173
|
-
# NORMAL AUTO-FIX
|
|
174
|
-
corrected = self.tool.correct(text)
|
|
175
|
-
|
|
176
|
-
# COPY TO CLIPBOARD IF REQUESTED
|
|
177
|
-
if copy_to_clipboard:
|
|
178
|
-
pyperclip.copy(corrected)
|
|
179
|
-
|
|
180
|
-
return corrected
|
|
181
|
-
|
|
182
|
-
# GET LIST OF SUPPORTED LANGUAGES
|
|
183
|
-
def get_supported_languages(self) -> List[Dict]:
|
|
184
|
-
"""GET LIST OF SUPPORTED LANGUAGES"""
|
|
185
|
-
try:
|
|
186
|
-
# GET LANGUAGES FROM LANGUAGE TOOL PUBLIC API
|
|
187
|
-
response = requests.get('https://api.languagetool.org/v2/languages')
|
|
188
|
-
languages = response.json()
|
|
189
|
-
|
|
190
|
-
# FORMAT LANGUAGES INTO REQUIRED STRUCTURE
|
|
191
|
-
formatted_langs = []
|
|
192
|
-
seen_codes = set()
|
|
193
|
-
|
|
194
|
-
# FORMAT LANGUAGES INTO REQUIRED STRUCTURE
|
|
195
|
-
for lang in languages:
|
|
196
|
-
code = lang['longCode'].split('-')[0]
|
|
197
|
-
|
|
198
|
-
# SKIP DUPLICATES
|
|
199
|
-
if code in seen_codes:
|
|
200
|
-
continue
|
|
201
|
-
|
|
202
|
-
# TEST IF LANGUAGE IS ACTUALLY SUPPORTED BY LOCAL TOOL
|
|
203
|
-
try:
|
|
204
|
-
self.tool.language = code
|
|
205
|
-
formatted_langs.append({
|
|
206
|
-
'code': code,
|
|
207
|
-
'name': lang['name'],
|
|
208
|
-
'variants': [v['name'] for v in lang.get('variants', [])]
|
|
209
|
-
})
|
|
210
|
-
seen_codes.add(code)
|
|
211
|
-
except:
|
|
212
|
-
continue
|
|
213
|
-
|
|
214
|
-
return formatted_langs
|
|
215
|
-
|
|
216
|
-
except Exception as e:
|
|
217
|
-
# IF API FAILS, GET LANGUAGES FROM LOCAL TOOL
|
|
218
|
-
try:
|
|
219
|
-
current_lang = self.tool.language
|
|
220
|
-
return [{'code': current_lang, 'name': current_lang.upper(), 'variants': []}]
|
|
221
|
-
except:
|
|
222
|
-
return []
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
from .core import translate_text, get_supported_languages
|
|
3
|
-
from ..utils.loading import LoadingAnimation
|
|
4
|
-
from ..utils.updates import check_for_updates
|
|
5
|
-
|
|
6
|
-
@click.command()
|
|
7
|
-
@click.argument('text', required=False)
|
|
8
|
-
@click.option('--to', default='en', help='Target language (default: en)')
|
|
9
|
-
@click.option('--from', 'from_lang', help='Source language (default: auto-detect)')
|
|
10
|
-
@click.option('--list-languages', is_flag=True, help='List all supported languages')
|
|
11
|
-
@click.option('--copy', is_flag=True, help='Copy translation to clipboard')
|
|
12
|
-
@click.option('--detect', is_flag=True, help='Show detected source language')
|
|
13
|
-
@click.option('--output', '-o', type=click.Path(), help='Save translation to file')
|
|
14
|
-
def autotranslate(text: str, to: str, from_lang: str, list_languages: bool,
|
|
15
|
-
copy: bool, detect: bool, output: str):
|
|
16
|
-
"""Translate text to specified language.
|
|
17
|
-
|
|
18
|
-
Supports automatic language detection, multiple target languages,
|
|
19
|
-
clipboard operations and file output. Use --list-languages to see
|
|
20
|
-
all supported language codes."""
|
|
21
|
-
# LIST ALL SUPPORTED LANGUAGES
|
|
22
|
-
if list_languages:
|
|
23
|
-
with LoadingAnimation():
|
|
24
|
-
click.echo("\nSupported Languages:")
|
|
25
|
-
for code, name in get_supported_languages().items():
|
|
26
|
-
click.echo(f"{code:<8} {name}")
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
# CHECK IF TEXT IS PROVIDED
|
|
30
|
-
if not text:
|
|
31
|
-
click.echo("Error: Please provide text to translate")
|
|
32
|
-
return
|
|
33
|
-
|
|
34
|
-
with LoadingAnimation():
|
|
35
|
-
result = translate_text(text, to_lang=to, from_lang=from_lang,
|
|
36
|
-
copy=copy, detect_lang=detect, output=output)
|
|
37
|
-
click.echo(result)
|
|
38
|
-
|
|
39
|
-
# UPDATE CHECK AT THE END
|
|
40
|
-
update_msg = check_for_updates()
|
|
41
|
-
if update_msg:
|
|
42
|
-
click.echo(update_msg)
|
autotools/autotranslate/core.py
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
from deep_translator import GoogleTranslator
|
|
2
|
-
from langdetect import detect
|
|
3
|
-
import pyperclip
|
|
4
|
-
|
|
5
|
-
def get_supported_languages() -> dict:
|
|
6
|
-
"""GET ALL SUPPORTED LANGUAGES FROM GOOGLE TRANSLATE"""
|
|
7
|
-
# GET LANGUAGES CODES
|
|
8
|
-
langs = GoogleTranslator().get_supported_languages(as_dict=True)
|
|
9
|
-
# SORT BY LANGUAGE NAME
|
|
10
|
-
return dict(sorted(langs.items(), key=lambda x: x[1].lower()))
|
|
11
|
-
|
|
12
|
-
def translate_text(text: str, to_lang: str = 'en', from_lang: str = None,
|
|
13
|
-
copy: bool = False, detect_lang: bool = False, output: str = None) -> str:
|
|
14
|
-
"""TRANSLATE TEXT TO SPECIFIED LANGUAGE
|
|
15
|
-
|
|
16
|
-
ARGS:
|
|
17
|
-
text (str): TEXT TO TRANSLATE
|
|
18
|
-
to_lang (str): TARGET LANGUAGE CODE (DEFAULT: EN)
|
|
19
|
-
from_lang (str): SOURCE LANGUAGE CODE (DEFAULT: AUTO-DETECT)
|
|
20
|
-
copy (bool): COPY RESULT TO CLIPBOARD
|
|
21
|
-
detect_lang (bool): SHOW DETECTED SOURCE LANGUAGE
|
|
22
|
-
output (str): PATH TO SAVE TRANSLATION TO FILE
|
|
23
|
-
|
|
24
|
-
RETURNS:
|
|
25
|
-
str: TRANSLATED TEXT
|
|
26
|
-
"""
|
|
27
|
-
# AUTO-DETECT SOURCE LANGUAGE IF NOT SPECIFIED
|
|
28
|
-
source_lang = from_lang or detect(text)
|
|
29
|
-
|
|
30
|
-
# TRANSLATE
|
|
31
|
-
translator = GoogleTranslator(source=source_lang, target=to_lang)
|
|
32
|
-
result = translator.translate(text)
|
|
33
|
-
|
|
34
|
-
# COPY TO CLIPBOARD IF REQUESTED
|
|
35
|
-
if copy:
|
|
36
|
-
pyperclip.copy(result)
|
|
37
|
-
|
|
38
|
-
# SAVE TO FILE IF OUTPUT PATH PROVIDED
|
|
39
|
-
if output:
|
|
40
|
-
try:
|
|
41
|
-
with open(output, 'w', encoding='utf-8') as f:
|
|
42
|
-
if detect_lang:
|
|
43
|
-
f.write(f"[Detected: {source_lang}] {result}")
|
|
44
|
-
else:
|
|
45
|
-
f.write(result)
|
|
46
|
-
except Exception as e:
|
|
47
|
-
print(f"\nError saving to file: {str(e)}")
|
|
48
|
-
|
|
49
|
-
# RETURN RESULT WITH DETECTED LANGUAGE IF REQUESTED
|
|
50
|
-
if detect_lang:
|
|
51
|
-
return f"[Detected: {source_lang}] {result}"
|
|
52
|
-
return result
|
autotools/test/__init__.py
DELETED
autotools/test/commands.py
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import click
|
|
2
|
-
import subprocess
|
|
3
|
-
import sys
|
|
4
|
-
import os
|
|
5
|
-
import re
|
|
6
|
-
from ..utils.updates import check_for_updates
|
|
7
|
-
|
|
8
|
-
@click.command()
|
|
9
|
-
@click.option('--unit', '-u', is_flag=True, help='Run only unit tests')
|
|
10
|
-
@click.option('--integration', '-i', is_flag=True, help='Run only integration tests')
|
|
11
|
-
@click.option('--no-cov', is_flag=True, help='Disable coverage report')
|
|
12
|
-
@click.option('--html', is_flag=True, help='Generate HTML coverage report')
|
|
13
|
-
@click.option('--module', '-m', help='Test specific module (e.g., autocaps, autolower)')
|
|
14
|
-
def test(unit, integration, no_cov, html, module):
|
|
15
|
-
"""Run test suite with various options."""
|
|
16
|
-
# CHECK IF PYTEST IS INSTALLED
|
|
17
|
-
try:
|
|
18
|
-
import pytest
|
|
19
|
-
import pytest_cov
|
|
20
|
-
except ImportError:
|
|
21
|
-
click.echo(click.style("\n❌ pytest and/or pytest-cov not found. Installing...", fg='yellow', bold=True))
|
|
22
|
-
try:
|
|
23
|
-
subprocess.run(['pip', 'install', 'pytest', 'pytest-cov'], check=True)
|
|
24
|
-
click.echo(click.style("✅ Successfully installed pytest and pytest-cov", fg='green', bold=True))
|
|
25
|
-
except subprocess.CalledProcessError as e:
|
|
26
|
-
click.echo(click.style(f"\n❌ Failed to install dependencies: {str(e)}", fg='red', bold=True))
|
|
27
|
-
sys.exit(1)
|
|
28
|
-
|
|
29
|
-
# BASE COMMAND WITH ENHANCED VERBOSITY
|
|
30
|
-
cmd = [
|
|
31
|
-
sys.executable, # USE SYSTEM PYTHON EXECUTABLE
|
|
32
|
-
'-m', 'pytest', # RUN PYTEST AS MODULE
|
|
33
|
-
'-vv', # VERY VERBOSE OUTPUT
|
|
34
|
-
'--capture=no', # SHOW PRINT STATEMENTS
|
|
35
|
-
'--showlocals', # SHOW LOCAL VARIABLES IN TRACEBACKS
|
|
36
|
-
'--log-cli-level=DEBUG', # SHOW DEBUG LOGS
|
|
37
|
-
'-s', # DISABLE CAPTURE
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
# COVERAGE OPTIONS
|
|
41
|
-
if not no_cov:
|
|
42
|
-
if html:
|
|
43
|
-
cmd.extend(['--cov-report=html', '--cov=autotools'])
|
|
44
|
-
else:
|
|
45
|
-
cmd.extend(['--cov-report=term-missing', '--cov=autotools'])
|
|
46
|
-
|
|
47
|
-
# TEST SELECTION
|
|
48
|
-
if module:
|
|
49
|
-
test_path = f'autotools/{module}/tests'
|
|
50
|
-
if unit and not integration:
|
|
51
|
-
test_path = f'{test_path}/unit'
|
|
52
|
-
elif integration and not unit:
|
|
53
|
-
test_path = f'{test_path}/integration'
|
|
54
|
-
cmd.append(test_path)
|
|
55
|
-
else:
|
|
56
|
-
cmd.append('autotools')
|
|
57
|
-
|
|
58
|
-
# SHOW COMMAND BEING RUN
|
|
59
|
-
click.echo(click.style("\nRunning tests with command:", fg='blue', bold=True))
|
|
60
|
-
click.echo(" ".join(cmd))
|
|
61
|
-
click.echo()
|
|
62
|
-
|
|
63
|
-
# RUN TESTS
|
|
64
|
-
try:
|
|
65
|
-
env = dict(os.environ)
|
|
66
|
-
env['PYTHONPATH'] = os.getcwd()
|
|
67
|
-
env['FORCE_COLOR'] = '1' # FORCE COLORS IN OUTPUT
|
|
68
|
-
|
|
69
|
-
process = subprocess.Popen(
|
|
70
|
-
cmd,
|
|
71
|
-
env=env,
|
|
72
|
-
stdout=subprocess.PIPE,
|
|
73
|
-
stderr=subprocess.STDOUT,
|
|
74
|
-
universal_newlines=True,
|
|
75
|
-
bufsize=1
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
# READ AND PROCESS OUTPUT IN REAL-TIME
|
|
79
|
-
while True:
|
|
80
|
-
line = process.stdout.readline()
|
|
81
|
-
if not line and process.poll() is not None:
|
|
82
|
-
break
|
|
83
|
-
if line:
|
|
84
|
-
# CLEAN THE LINE
|
|
85
|
-
line = line.strip()
|
|
86
|
-
if line: # ONLY PROCESS NON-EMPTY LINES
|
|
87
|
-
if '::' in line and 'autotools/' in line:
|
|
88
|
-
# REMOVE PARENT DIRECTORY PATHS
|
|
89
|
-
line = line.split('autotools/')[-1].replace('/tests/', '/')
|
|
90
|
-
# REMOVE MODULE PARENT DIRECTORY
|
|
91
|
-
parts = line.split('/')
|
|
92
|
-
if len(parts) > 1:
|
|
93
|
-
line = parts[-1]
|
|
94
|
-
# REMOVE MULTIPLE SPACES AND DOTS
|
|
95
|
-
line = re.sub(r'\s+', ' ', line)
|
|
96
|
-
line = re.sub(r'\.+', '.', line)
|
|
97
|
-
# REMOVE EMPTY LINES WITH JUST DOTS OR SPACES
|
|
98
|
-
if line.strip('. '):
|
|
99
|
-
sys.stdout.write(line + '\n')
|
|
100
|
-
sys.stdout.flush()
|
|
101
|
-
|
|
102
|
-
process.wait()
|
|
103
|
-
if process.returncode == 0:
|
|
104
|
-
click.echo(click.style("\n✅ All tests passed!", fg='green', bold=True))
|
|
105
|
-
else:
|
|
106
|
-
click.echo(click.style("\n❌ Some tests failed!", fg='red', bold=True))
|
|
107
|
-
sys.exit(1)
|
|
108
|
-
except subprocess.CalledProcessError as e:
|
|
109
|
-
click.echo(click.style(f"\n❌ Tests failed with return code {e.returncode}", fg='red', bold=True))
|
|
110
|
-
sys.exit(1)
|
|
111
|
-
except Exception as e:
|
|
112
|
-
click.echo(click.style(f"\n❌ Error running tests: {str(e)}", fg='red', bold=True))
|
|
113
|
-
sys.exit(1)
|
|
114
|
-
|
|
115
|
-
# UPDATE CHECK AT THE END
|
|
116
|
-
update_msg = check_for_updates()
|
|
117
|
-
if update_msg:
|
|
118
|
-
click.echo(update_msg)
|
|
File without changes
|
|
File without changes
|