maya-cli 0.1.2__py3-none-any.whl → 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.
- maya_cli/cli.py +503 -211
- maya_cli/refactor.py +5 -4
- {maya_cli-0.1.2.dist-info → maya_cli-0.1.4.dist-info}/METADATA +64 -7
- maya_cli-0.1.4.dist-info/RECORD +11 -0
- {maya_cli-0.1.2.dist-info → maya_cli-0.1.4.dist-info}/WHEEL +1 -1
- maya_cli-0.1.2.dist-info/RECORD +0 -11
- {maya_cli-0.1.2.dist-info → maya_cli-0.1.4.dist-info}/entry_points.txt +0 -0
- {maya_cli-0.1.2.dist-info → maya_cli-0.1.4.dist-info}/top_level.txt +0 -0
maya_cli/cli.py
CHANGED
@@ -8,6 +8,7 @@ import openai
|
|
8
8
|
from .project_generator import create_project_structure, PROJECT_STRUCTURE
|
9
9
|
from .refactor import process_directory
|
10
10
|
from maya_cli.scripts import optimize # This will trigger optimize_event_handler automatically
|
11
|
+
import subprocess
|
11
12
|
|
12
13
|
|
13
14
|
# Setup logging
|
@@ -21,6 +22,107 @@ logging.basicConfig(
|
|
21
22
|
# Load environment variables from .env
|
22
23
|
load_dotenv()
|
23
24
|
|
25
|
+
# ✅ Function to check if OPENAI_API_KEY is set before executing commands
|
26
|
+
def require_openai_key():
|
27
|
+
"""Ensure the OpenAI API key is set before executing commands."""
|
28
|
+
api_key = get_openai_key()
|
29
|
+
|
30
|
+
if not api_key:
|
31
|
+
logging.error("❌ OPENAI_API_KEY is not set. Please set it before proceeding.")
|
32
|
+
print("❌ OPENAI_API_KEY is not set. Please set it before proceeding.")
|
33
|
+
oak = input("Enter OPENAI_API_KEY: ").strip()
|
34
|
+
|
35
|
+
if not oak:
|
36
|
+
print("❌ No API key provided. Exiting.")
|
37
|
+
sys.exit(1)
|
38
|
+
|
39
|
+
set_env_func("OPENAI_API_KEY", oak) # Call set_env to save the key
|
40
|
+
|
41
|
+
verify_openai_key()
|
42
|
+
|
43
|
+
verify_openai_key()
|
44
|
+
|
45
|
+
def get_openai_key():
|
46
|
+
"""Retrieve the OpenAI API key, checking multiple sources."""
|
47
|
+
api_key = os.getenv("OPENAI_API_KEY") # Check normal env first
|
48
|
+
|
49
|
+
if not api_key:
|
50
|
+
# ✅ Force fetch from User-level env variables in Windows
|
51
|
+
if os.name == "nt":
|
52
|
+
api_key = subprocess.run(
|
53
|
+
["powershell", "-Command",
|
54
|
+
'[System.Environment]::GetEnvironmentVariable("OPENAI_API_KEY", "User")'],
|
55
|
+
capture_output=True, text=True
|
56
|
+
).stdout.strip()
|
57
|
+
|
58
|
+
return api_key
|
59
|
+
|
60
|
+
# ✅ CLI Command to set environment variables
|
61
|
+
@click.command()
|
62
|
+
@click.argument("key")
|
63
|
+
@click.argument("value")
|
64
|
+
def set_env(key, value):
|
65
|
+
set_env_func(key, value)
|
66
|
+
|
67
|
+
def set_env_func(key, value):
|
68
|
+
"""Set an environment variable in .env file."""
|
69
|
+
env_file = ".env"
|
70
|
+
|
71
|
+
try:
|
72
|
+
if not os.path.exists(env_file):
|
73
|
+
with open(env_file, "w") as f:
|
74
|
+
f.write("# Maya CLI Environment Variables\n")
|
75
|
+
logging.info("Created new .env file.")
|
76
|
+
|
77
|
+
set_key(env_file, key, value)
|
78
|
+
|
79
|
+
# ✅ Set environment variable for current session
|
80
|
+
os.environ[key] = value
|
81
|
+
|
82
|
+
# ✅ Set environment variable permanently (Windows & Linux/Mac)
|
83
|
+
if os.name == "nt": # Windows
|
84
|
+
os.system(f'setx {key} "{value}"')
|
85
|
+
|
86
|
+
# Set for PowerShell (User Scope)
|
87
|
+
subprocess.run(["powershell", "-Command",
|
88
|
+
f'[System.Environment]::SetEnvironmentVariable("{key}", "{value}", "User")'])
|
89
|
+
|
90
|
+
# ✅ Immediately update PowerShell session so $env:OPENAI_API_KEY works instantly
|
91
|
+
subprocess.run(["powershell", "-Command",
|
92
|
+
f'$env:{key} = "{value}"'])
|
93
|
+
|
94
|
+
print(f"✅ Environment variable '{key}' set successfully for CMD & PowerShell!")
|
95
|
+
|
96
|
+
else: # Linux/Mac
|
97
|
+
os.system(f'export {key}="{value}"')
|
98
|
+
|
99
|
+
click.echo(f"✅ Environment variable '{key}' set successfully!")
|
100
|
+
logging.info(f"Set environment variable: {key}={value}")
|
101
|
+
|
102
|
+
except Exception as e:
|
103
|
+
logging.error(f"Error setting environment variable {key}: {str(e)}")
|
104
|
+
click.echo(f"❌ Error setting environment variable: {str(e)}")
|
105
|
+
|
106
|
+
# ✅ Function to verify OpenAI API key is set
|
107
|
+
def verify_openai_key():
|
108
|
+
"""Check if OPENAI_API_KEY is set in environment variables."""
|
109
|
+
openai_key = os.getenv("OPENAI_API_KEY")
|
110
|
+
if not openai_key:
|
111
|
+
logging.error("OPENAI_API_KEY is not set. Please set it before proceeding.")
|
112
|
+
return False
|
113
|
+
pass
|
114
|
+
|
115
|
+
# ✅ Function to execute CLI commands
|
116
|
+
def execute_maya_cli_command(command):
|
117
|
+
"""Executes a CLI command after verifying the OpenAI API key."""
|
118
|
+
if not verify_openai_key():
|
119
|
+
return
|
120
|
+
|
121
|
+
try:
|
122
|
+
result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True)
|
123
|
+
logging.info("Command Output:\n%s", result.stdout.strip())
|
124
|
+
except subprocess.CalledProcessError as e:
|
125
|
+
logging.error("Error executing command: %s", e.stderr.strip())
|
24
126
|
|
25
127
|
@click.group()
|
26
128
|
def maya():
|
@@ -31,6 +133,7 @@ def maya():
|
|
31
133
|
@click.command()
|
32
134
|
@click.argument("project_name")
|
33
135
|
def create(project_name):
|
136
|
+
require_openai_key()
|
34
137
|
"""Create a new AI project structure"""
|
35
138
|
try:
|
36
139
|
base_path = os.path.join(os.getcwd(), project_name)
|
@@ -50,149 +153,125 @@ def create(project_name):
|
|
50
153
|
|
51
154
|
|
52
155
|
@click.command()
|
53
|
-
@click.argument("
|
54
|
-
|
55
|
-
|
56
|
-
"""CLI Command: maya check
|
156
|
+
@click.argument("path", nargs=-1, required=True)
|
157
|
+
def check_best_practices(path):
|
158
|
+
require_openai_key()
|
159
|
+
"""CLI Command: maya check-best-practices [folder] [sub-folder] ... [filename]"""
|
57
160
|
click.echo("🚀 Running Best Practices Check...")
|
161
|
+
|
58
162
|
base_path = os.getcwd()
|
59
|
-
|
163
|
+
target_path = os.path.join(base_path, *path)
|
164
|
+
|
165
|
+
if not os.path.exists(target_path):
|
166
|
+
click.echo(f"❌ Path '{target_path}' does not exist.")
|
167
|
+
return
|
60
168
|
|
61
|
-
if
|
62
|
-
|
169
|
+
if os.path.isdir(target_path):
|
170
|
+
process_directory(target_path)
|
171
|
+
elif os.path.isfile(target_path):
|
172
|
+
process_directory(os.path.dirname(target_path), os.path.basename(target_path))
|
173
|
+
else:
|
174
|
+
click.echo("❌ Invalid path provided.")
|
63
175
|
return
|
64
176
|
|
65
|
-
process_directory(target_directory, filename)
|
66
177
|
click.echo("✅ Best practices check completed!")
|
67
178
|
|
68
|
-
|
69
179
|
@click.command()
|
70
|
-
@click.argument("
|
71
|
-
@click.argument("
|
72
|
-
|
73
|
-
|
74
|
-
|
180
|
+
@click.argument("parent_folder", required=True)
|
181
|
+
@click.argument("sub_folder", required=True)
|
182
|
+
@click.argument("filename", required=True)
|
183
|
+
def optimize(parent_folder, sub_folder, filename):
|
184
|
+
require_openai_key()
|
185
|
+
"""Optimize a file by importing optimize.py from maya_cli.scripts."""
|
75
186
|
|
76
|
-
|
77
|
-
|
78
|
-
with open(env_file, "w") as f:
|
79
|
-
f.write("# Maya CLI Environment Variables\n")
|
80
|
-
logging.info("Created new .env file.")
|
81
|
-
|
82
|
-
set_key(env_file, key, value)
|
83
|
-
click.echo(f"✅ Environment variable '{key}' set successfully!")
|
84
|
-
logging.info(f"Set environment variable: {key}={value}")
|
187
|
+
# Construct the full file path
|
188
|
+
target_path = os.path.abspath(os.path.join(parent_folder, sub_folder, filename))
|
85
189
|
|
86
|
-
|
87
|
-
|
88
|
-
|
190
|
+
if not os.path.isfile(target_path):
|
191
|
+
click.echo(f"❌ Error: '{target_path}' is not a valid file.")
|
192
|
+
logging.error(f"Invalid file provided: {target_path}")
|
193
|
+
return
|
89
194
|
|
195
|
+
# Inject the import statement into the file
|
196
|
+
inject_import(target_path)
|
90
197
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
198
|
+
def inject_import(filepath):
|
199
|
+
"""Inject import statement for optimize.py into the target file."""
|
200
|
+
try:
|
201
|
+
import_statement = "from maya_cli.scripts import optimize\n"
|
202
|
+
|
203
|
+
with open(filepath, "r+", encoding="utf-8") as f:
|
204
|
+
content = f.readlines()
|
205
|
+
|
206
|
+
# Check if the import already exists
|
207
|
+
if any(line.strip() == import_statement.strip() for line in content):
|
208
|
+
click.echo(f"✅ {filepath} already imports optimize.py.")
|
209
|
+
return
|
210
|
+
|
211
|
+
# Insert import at the top
|
212
|
+
content.insert(0, import_statement)
|
213
|
+
f.seek(0)
|
214
|
+
f.writelines(content)
|
215
|
+
|
216
|
+
click.echo(f"✅ Imported optimize.py into {filepath}")
|
217
|
+
logging.info(f"Imported optimize.py into {filepath}")
|
108
218
|
|
219
|
+
except Exception as e:
|
220
|
+
logging.error(f"Error injecting import into '{filepath}': {str(e)}")
|
221
|
+
click.echo(f"❌ Error injecting import into '{filepath}': {str(e)}")
|
109
222
|
|
110
|
-
def optimize_file(filepath, fine_tune_enabled):
|
111
|
-
"""Dynamically import optimize.py into the specified file."""
|
112
|
-
try:
|
113
|
-
module_name = "scripts.optimize"
|
114
|
-
spec = importlib.util.spec_from_file_location(module_name, "scripts/optimize.py")
|
115
|
-
optimize_module = importlib.util.module_from_spec(spec)
|
116
|
-
spec.loader.exec_module(optimize_module)
|
117
223
|
|
118
|
-
|
119
|
-
|
224
|
+
@click.command()
|
225
|
+
@click.argument("parent_folder", required=True)
|
226
|
+
@click.argument("sub_folder", required=True)
|
227
|
+
@click.argument("filename", required=True)
|
228
|
+
def is_secured(parent_folder, sub_folder, filename):
|
229
|
+
require_openai_key()
|
230
|
+
"""Check and enforce API security measures: Authentication, Encryption, and Rate Limiting."""
|
231
|
+
click.echo("🔍 Running API Security Check...")
|
120
232
|
|
121
|
-
|
122
|
-
|
123
|
-
click.echo("🚀 Fine-tuning enabled!")
|
233
|
+
# Construct the full file path
|
234
|
+
target_path = os.path.abspath(os.path.join(parent_folder, sub_folder, filename))
|
124
235
|
|
125
|
-
|
126
|
-
|
127
|
-
|
236
|
+
if not os.path.isfile(target_path):
|
237
|
+
click.echo(f"❌ Error: '{target_path}' is not a valid file.")
|
238
|
+
logging.error(f"Invalid file provided: {target_path}")
|
239
|
+
return
|
128
240
|
|
241
|
+
try:
|
242
|
+
with open(target_path, "r", encoding="utf-8") as f:
|
243
|
+
code_content = f.read()
|
129
244
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
for file in files:
|
134
|
-
if file.endswith(".py"):
|
135
|
-
optimize_file(os.path.join(root, file), fine_tune_enabled)
|
245
|
+
# Validate security using AI
|
246
|
+
validation_feedback = validate_security_with_ai(code_content)
|
247
|
+
security_issues = []
|
136
248
|
|
249
|
+
if not validation_feedback.get("authentication", False):
|
250
|
+
security_issues.append(f"❌ Missing API Authentication. Applying OAuth/API Key authentication.")
|
251
|
+
apply_api_authentication(target_path)
|
137
252
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
import scripts.optimize
|
253
|
+
if not validation_feedback.get("encryption", False):
|
254
|
+
security_issues.append(f"❌ Missing Data Encryption. Implementing encryption protocols.")
|
255
|
+
apply_data_encryption(target_path)
|
142
256
|
|
143
|
-
|
144
|
-
|
257
|
+
if not validation_feedback.get("rate_limiting", False):
|
258
|
+
security_issues.append(f"❌ No Rate Limiting detected. Implementing rate limiting & quotas.")
|
259
|
+
apply_rate_limiting(target_path)
|
145
260
|
|
146
|
-
if
|
147
|
-
|
148
|
-
|
261
|
+
if security_issues:
|
262
|
+
for issue in security_issues:
|
263
|
+
click.echo(f"⚠️ {issue}")
|
264
|
+
click.echo("✅ Security measures have been enforced!")
|
265
|
+
else:
|
266
|
+
click.echo("✅ API usage is secure. No changes needed.")
|
149
267
|
|
150
268
|
except Exception as e:
|
151
|
-
logging.error(f"Error
|
152
|
-
click.echo(f"❌ Error
|
269
|
+
logging.error(f"❌ Error processing {target_path}: {str(e)}")
|
270
|
+
click.echo(f"❌ Error processing {target_path}: {str(e)}")
|
153
271
|
|
154
|
-
@click.command()
|
155
|
-
@click.argument("target")
|
156
|
-
@click.argument("filename", required=False)
|
157
|
-
def isSecured(target, filename=None):
|
158
|
-
"""Check and enforce API security measures: Authentication, Encryption, and Rate Limiting."""
|
159
|
-
click.echo("\U0001F50D Running API Security Check...")
|
160
|
-
security_issues = []
|
161
|
-
|
162
|
-
# Determine path to check
|
163
|
-
if filename:
|
164
|
-
files_to_check = [os.path.join(target, filename)]
|
165
|
-
else:
|
166
|
-
files_to_check = [os.path.join(target, f) for f in os.listdir(target) if f.endswith(".py")]
|
167
|
-
|
168
|
-
for file in files_to_check:
|
169
|
-
with open(file, "r") as f:
|
170
|
-
code_content = f.read()
|
171
|
-
|
172
|
-
# Validate security using OpenAI
|
173
|
-
validation_feedback = validate_security_with_ai(code_content)
|
174
|
-
|
175
|
-
if not validation_feedback.get("authentication", False):
|
176
|
-
security_issues.append(f"{file}: Missing API Authentication. Applying OAuth/API Key authentication.")
|
177
|
-
apply_api_authentication(file)
|
178
|
-
|
179
|
-
if not validation_feedback.get("encryption", False):
|
180
|
-
security_issues.append(f"{file}: Missing Data Encryption. Implementing encryption protocols.")
|
181
|
-
apply_data_encryption(file)
|
182
|
-
|
183
|
-
if not validation_feedback.get("rate_limiting", False):
|
184
|
-
security_issues.append(f"{file}: No Rate Limiting detected. Implementing rate limiting & quotas.")
|
185
|
-
apply_rate_limiting(file)
|
186
|
-
|
187
|
-
if security_issues:
|
188
|
-
for issue in security_issues:
|
189
|
-
click.echo(f"⚠️ {issue}")
|
190
|
-
click.echo("✅ Security measures have been enforced!")
|
191
|
-
else:
|
192
|
-
click.echo("✅ API Usage is secure. No changes needed.")
|
193
|
-
|
194
272
|
logging.info("API Security Check Completed.")
|
195
273
|
|
274
|
+
|
196
275
|
def validate_security_with_ai(code):
|
197
276
|
"""Use OpenAI to validate security measures in the given code."""
|
198
277
|
prompt = f"""
|
@@ -201,162 +280,370 @@ def validate_security_with_ai(code):
|
|
201
280
|
1. Secure API Authentication (OAuth or API Keys)
|
202
281
|
2. Proper Data Encryption Protocols for sensitive data
|
203
282
|
3. Rate Limiting and Quotas to prevent API abuse
|
204
|
-
|
283
|
+
|
205
284
|
Return a JSON response with keys: authentication, encryption, rate_limiting, each set to True or False.
|
206
|
-
|
285
|
+
|
207
286
|
Code:
|
208
287
|
```
|
209
288
|
{code}
|
210
289
|
```
|
211
290
|
"""
|
212
|
-
|
213
|
-
response = openai.ChatCompletion.create(
|
214
|
-
model="gpt-4",
|
215
|
-
messages=[{"role": "system", "content": prompt}]
|
216
|
-
)
|
217
|
-
|
218
|
-
result = response["choices"][0]["message"]["content"]
|
219
|
-
|
291
|
+
|
220
292
|
try:
|
293
|
+
response = openai.ChatCompletion.create(
|
294
|
+
model="gpt-4",
|
295
|
+
messages=[{"role": "system", "content": prompt}],
|
296
|
+
)
|
297
|
+
|
298
|
+
result = response["choices"][0]["message"]["content"]
|
221
299
|
return json.loads(result)
|
222
|
-
|
300
|
+
|
301
|
+
except Exception as e:
|
302
|
+
logging.error(f"Error in AI validation: {str(e)}")
|
223
303
|
return {"authentication": False, "encryption": False, "rate_limiting": False}
|
224
304
|
|
305
|
+
|
225
306
|
def apply_api_authentication(filepath):
|
226
307
|
"""Apply OAuth or API Key authentication to the specified file."""
|
227
308
|
logging.info(f"Applying OAuth/API Key Authentication to {filepath}.")
|
228
|
-
with open(filepath, "a") as f:
|
229
|
-
f.write("\n#
|
309
|
+
with open(filepath, "a", encoding="utf-8") as f:
|
310
|
+
f.write("\n# TODO: Implement OAuth/API Key Authentication\n")
|
311
|
+
|
230
312
|
|
231
313
|
def apply_data_encryption(filepath):
|
232
314
|
"""Implement data encryption protocols in the specified file."""
|
233
315
|
logging.info(f"Applying Data Encryption Protocols to {filepath}.")
|
234
|
-
with open(filepath, "a") as f:
|
235
|
-
f.write("\n#
|
316
|
+
with open(filepath, "a", encoding="utf-8") as f:
|
317
|
+
f.write("\n# TODO: Implement Data Encryption\n")
|
318
|
+
|
236
319
|
|
237
320
|
def apply_rate_limiting(filepath):
|
238
321
|
"""Implement API rate limiting and quotas in the specified file."""
|
239
322
|
logging.info(f"Applying Rate Limiting & Quotas to {filepath}.")
|
240
|
-
with open(filepath, "a") as f:
|
241
|
-
f.write("\n#
|
323
|
+
with open(filepath, "a", encoding="utf-8") as f:
|
324
|
+
f.write("\n# TODO: Enforce API Rate Limiting & Quotas\n")
|
325
|
+
|
242
326
|
|
243
327
|
@click.command()
|
244
|
-
@click.argument("
|
328
|
+
@click.argument("parent_folder", required=True)
|
329
|
+
@click.argument("sub_folder", required=True)
|
245
330
|
@click.argument("filename", required=False)
|
246
|
-
def check_ethics(
|
331
|
+
def check_ethics(parent_folder, sub_folder, filename=None):
|
332
|
+
require_openai_key()
|
247
333
|
"""Check code for efficiency, accuracy, and best practices."""
|
248
|
-
click.echo("
|
249
|
-
|
250
|
-
|
334
|
+
click.echo("\U0001F50D Running Code Ethics Check...")
|
335
|
+
ethics_issues = []
|
336
|
+
|
337
|
+
# Construct the full path
|
338
|
+
target_path = os.path.abspath(os.path.join(parent_folder, sub_folder))
|
339
|
+
|
340
|
+
if not os.path.isdir(target_path):
|
341
|
+
click.echo(f"❌ Error: '{target_path}' is not a valid directory.")
|
342
|
+
logging.error(f"Invalid directory provided: {target_path}")
|
343
|
+
return
|
344
|
+
|
345
|
+
# Determine files to check
|
346
|
+
if filename:
|
347
|
+
files_to_check = [os.path.join(target_path, filename)]
|
348
|
+
if not os.path.isfile(files_to_check[0]):
|
349
|
+
click.echo(f"❌ Error: '{files_to_check[0]}' is not a valid file.")
|
350
|
+
logging.error(f"Invalid file provided: {files_to_check[0]}")
|
351
|
+
return
|
352
|
+
else:
|
353
|
+
files_to_check = [
|
354
|
+
os.path.join(target_path, f) for f in os.listdir(target_path) if f.endswith(".py")
|
355
|
+
]
|
356
|
+
|
357
|
+
for file in files_to_check:
|
358
|
+
try:
|
359
|
+
with open(file, "r", encoding="utf-8") as f:
|
360
|
+
code_content = f.read()
|
361
|
+
|
362
|
+
# Validate ethics using AI
|
363
|
+
validation_feedback = validate_ethics_with_ai(code_content)
|
364
|
+
|
365
|
+
if not validation_feedback.get("efficiency", False):
|
366
|
+
ethics_issues.append(f"{file}: Code may have performance inefficiencies.")
|
367
|
+
|
368
|
+
if not validation_feedback.get("accuracy", False):
|
369
|
+
ethics_issues.append(f"{file}: Code accuracy needs review for correctness.")
|
370
|
+
|
371
|
+
if not validation_feedback.get("best_practices", False):
|
372
|
+
ethics_issues.append(f"{file}: Code may not follow industry best practices.")
|
373
|
+
|
374
|
+
except Exception as e:
|
375
|
+
logging.error(f"❌ Error processing {file}: {str(e)}")
|
376
|
+
click.echo(f"❌ Error processing {file}: {str(e)}")
|
377
|
+
|
378
|
+
if ethics_issues:
|
379
|
+
for issue in ethics_issues:
|
380
|
+
click.echo(f"⚠️ {issue}")
|
381
|
+
click.echo("✅ Ethics Review Completed with Recommendations!")
|
382
|
+
else:
|
383
|
+
click.echo("✅ Code meets ethical standards. No issues detected.")
|
384
|
+
|
385
|
+
logging.info("Code Ethics Check Completed.")
|
386
|
+
|
387
|
+
|
388
|
+
def validate_ethics_with_ai(code):
|
389
|
+
"""Use OpenAI to validate code ethics, efficiency, and best practices."""
|
390
|
+
prompt = f"""
|
391
|
+
Analyze the following Python code for ethical concerns in:
|
392
|
+
1. Efficiency (performance optimization, unnecessary loops, redundant code)
|
393
|
+
2. Accuracy (logical correctness, potential calculation errors)
|
394
|
+
3. Best Practices (PEP8 compliance, maintainability, documentation)
|
395
|
+
|
396
|
+
Return a JSON response with keys: efficiency, accuracy, best_practices, each set to True or False.
|
397
|
+
|
398
|
+
Code:
|
399
|
+
```
|
400
|
+
{code}
|
401
|
+
```
|
402
|
+
"""
|
403
|
+
|
404
|
+
try:
|
405
|
+
response = openai.ChatCompletion.create(
|
406
|
+
model="gpt-4",
|
407
|
+
messages=[{"role": "system", "content": prompt}],
|
408
|
+
)
|
409
|
+
|
410
|
+
result = response["choices"][0]["message"]["content"]
|
411
|
+
return json.loads(result)
|
412
|
+
|
413
|
+
except Exception as e:
|
414
|
+
logging.error(f"Error in AI validation: {str(e)}")
|
415
|
+
return {"efficiency": False, "accuracy": False, "best_practices": False}
|
416
|
+
|
251
417
|
|
252
418
|
@click.command()
|
253
|
-
@click.argument("
|
419
|
+
@click.argument("parent_folder")
|
420
|
+
@click.argument("sub_folder")
|
254
421
|
@click.argument("filename")
|
255
|
-
def doc(
|
422
|
+
def doc(parent_folder, sub_folder, filename):
|
423
|
+
require_openai_key()
|
256
424
|
"""Generate README.md documentation for the given file."""
|
257
425
|
click.echo("📄 Generating Documentation...")
|
258
|
-
|
259
|
-
|
426
|
+
|
427
|
+
# Construct the full file path
|
428
|
+
target_path = os.path.join(parent_folder, sub_folder)
|
429
|
+
file_path = os.path.join(target_path, filename)
|
430
|
+
|
431
|
+
# Validate directory existence
|
432
|
+
if not os.path.isdir(target_path):
|
433
|
+
click.echo(f"❌ Error: The directory '{target_path}' does not exist.")
|
434
|
+
return
|
435
|
+
|
436
|
+
# Validate file existence
|
437
|
+
if not os.path.isfile(file_path):
|
438
|
+
click.echo(f"❌ Error: The file '{file_path}' does not exist in the specified directory.")
|
439
|
+
return
|
440
|
+
|
441
|
+
readme_path = os.path.join(target_path, "README.md")
|
442
|
+
|
443
|
+
try:
|
444
|
+
with open(file_path, "r", encoding="utf-8") as source_file:
|
445
|
+
code_content = source_file.read()
|
446
|
+
|
447
|
+
# Generate documentation (Placeholder function, replace with AI-based generation)
|
448
|
+
documentation = generate_documentation(code_content)
|
449
|
+
|
450
|
+
# Write to README.md
|
451
|
+
with open(readme_path, "w", encoding="utf-8") as readme_file:
|
452
|
+
readme_file.write(documentation)
|
453
|
+
|
454
|
+
click.echo(f"✅ Documentation created for {file_path} -> {readme_path}")
|
455
|
+
|
456
|
+
except Exception as e:
|
457
|
+
logging.error(f"❌ Error processing {file_path}: {str(e)}")
|
458
|
+
click.echo(f"❌ Error processing {file_path}: {str(e)}")
|
459
|
+
|
460
|
+
def generate_documentation(code):
|
461
|
+
"""Generate structured documentation based on the given Python code."""
|
462
|
+
return f"# Auto-Generated Documentation\n\n```python\n{code}\n```"
|
463
|
+
|
260
464
|
|
261
465
|
@click.command()
|
262
|
-
@click.argument("
|
263
|
-
@click.argument("
|
264
|
-
|
265
|
-
|
466
|
+
@click.argument("parent_folder")
|
467
|
+
@click.argument("sub_folder")
|
468
|
+
@click.argument("filename", required=False)
|
469
|
+
def codex(parent_folder, sub_folder, filename=None):
|
470
|
+
require_openai_key()
|
471
|
+
"""Provide in-depth analysis and recommendations for a file or all Python files in a directory."""
|
266
472
|
click.echo("📚 Creating Code Codex Report...")
|
267
|
-
|
268
|
-
|
473
|
+
|
474
|
+
# Construct the full target path
|
475
|
+
target_path = os.path.join(parent_folder, sub_folder)
|
476
|
+
|
477
|
+
# Validate directory existence
|
478
|
+
if not os.path.isdir(target_path):
|
479
|
+
click.echo(f"❌ Error: The directory '{target_path}' does not exist.")
|
480
|
+
return
|
481
|
+
|
482
|
+
# Determine files to analyze
|
483
|
+
if filename:
|
484
|
+
file_path = os.path.join(target_path, filename)
|
485
|
+
if not os.path.isfile(file_path):
|
486
|
+
click.echo(f"❌ Error: The file '{file_path}' does not exist in the specified directory.")
|
487
|
+
return
|
488
|
+
files_to_analyze = [file_path]
|
489
|
+
else:
|
490
|
+
files_to_analyze = [os.path.join(target_path, f) for f in os.listdir(target_path) if f.endswith(".py")]
|
491
|
+
|
492
|
+
if not files_to_analyze:
|
493
|
+
click.echo("⚠️ No Python files found in the specified directory.")
|
494
|
+
return
|
495
|
+
|
496
|
+
for file in files_to_analyze:
|
497
|
+
codex_report_path = os.path.join(".\\docs/", "CODEX_REPORT.md")
|
498
|
+
|
499
|
+
try:
|
500
|
+
with open(file, "r", encoding="utf-8") as source_file:
|
501
|
+
code_content = source_file.read()
|
502
|
+
|
503
|
+
# Generate codex report (Placeholder function, replace with AI-based analysis)
|
504
|
+
report = generate_codex_report(code_content)
|
505
|
+
|
506
|
+
# Write report to CODEX_REPORT.md
|
507
|
+
with open(codex_report_path, "w", encoding="utf-8") as report_file:
|
508
|
+
report_file.write(report)
|
509
|
+
|
510
|
+
click.echo(f"✅ Codex Report generated for {file} -> {codex_report_path}")
|
511
|
+
|
512
|
+
except Exception as e:
|
513
|
+
logging.error(f"❌ Error processing {file}: {str(e)}")
|
514
|
+
click.echo(f"❌ Error processing {file}: {str(e)}")
|
515
|
+
|
516
|
+
def generate_codex_report(code):
|
517
|
+
"""Generate an in-depth analysis and recommendations based on the given Python code."""
|
518
|
+
return f"# Code Analysis & Recommendations\n\n```python\n{code}\n```\n\n## Recommendations:\n- Improve efficiency\n- Enhance readability\n- Optimize performance\n"
|
519
|
+
|
269
520
|
|
270
521
|
@click.command()
|
271
|
-
@click.argument("
|
522
|
+
@click.argument("parent_folder")
|
523
|
+
@click.argument("sub_folder")
|
272
524
|
@click.argument("filename", required=False)
|
273
|
-
def regulate(
|
525
|
+
def regulate(parent_folder, sub_folder, filename=None):
|
526
|
+
# Ensure OpenAI API key is available before running logic
|
527
|
+
require_openai_key()
|
528
|
+
|
274
529
|
"""Ensure code compliance with GDPR, CCPA, AI Act, and ISO 42001 AI governance standards."""
|
275
530
|
click.echo("🔍 Running Compliance & Regulation Check...")
|
531
|
+
|
276
532
|
compliance_issues = []
|
277
|
-
|
278
|
-
#
|
533
|
+
|
534
|
+
# Construct the full target path
|
535
|
+
target_path = os.path.join(parent_folder, sub_folder)
|
536
|
+
|
537
|
+
# Validate directory existence
|
538
|
+
if not os.path.isdir(target_path):
|
539
|
+
click.echo(f"❌ Error: The directory '{target_path}' does not exist.")
|
540
|
+
return
|
541
|
+
|
542
|
+
# Determine files to check
|
279
543
|
if filename:
|
280
|
-
|
544
|
+
file_path = os.path.join(target_path, filename)
|
545
|
+
if not os.path.isfile(file_path):
|
546
|
+
click.echo(f"❌ Error: The file '{file_path}' does not exist in the specified directory.")
|
547
|
+
return
|
548
|
+
files_to_check = [file_path]
|
281
549
|
else:
|
282
|
-
files_to_check = [os.path.join(
|
283
|
-
|
550
|
+
files_to_check = [os.path.join(target_path, f) for f in os.listdir(target_path) if f.endswith(".py")]
|
551
|
+
|
552
|
+
if not files_to_check:
|
553
|
+
click.echo("⚠️ No Python files found in the specified directory.")
|
554
|
+
return
|
555
|
+
|
284
556
|
for file in files_to_check:
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
557
|
+
compliance_report_path = os.path.join("./configs/", "COMPLIANCE_REPORT.md")
|
558
|
+
|
559
|
+
try:
|
560
|
+
with open(file, "r", encoding="utf-8") as f:
|
561
|
+
code_content = f.read()
|
562
|
+
|
563
|
+
# Validate compliance (Placeholder function, replace with AI-based analysis)
|
564
|
+
compliance_feedback = validate_compliance_with_ai(code_content)
|
565
|
+
|
566
|
+
# Track issues and apply fixes
|
567
|
+
if not compliance_feedback.get("gdpr", False):
|
568
|
+
compliance_issues.append(f"{file}: GDPR compliance issues detected. Adjusting for data privacy.")
|
569
|
+
apply_gdpr_compliance(file)
|
570
|
+
|
571
|
+
if not compliance_feedback.get("ccpa", False):
|
572
|
+
compliance_issues.append(f"{file}: CCPA compliance issues detected. Ensuring consumer rights protection.")
|
573
|
+
apply_ccpa_compliance(file)
|
574
|
+
|
575
|
+
if not compliance_feedback.get("ai_act", False):
|
576
|
+
compliance_issues.append(f"{file}: AI Act risk classification missing. Implementing compliance measures.")
|
577
|
+
apply_ai_act_compliance(file)
|
578
|
+
|
579
|
+
if not compliance_feedback.get("iso_42001", False):
|
580
|
+
compliance_issues.append(f"{file}: ISO 42001 AI governance framework not followed. Adjusting AI management protocols.")
|
581
|
+
apply_iso_42001_compliance(file)
|
582
|
+
|
583
|
+
# Generate compliance report
|
584
|
+
with open(compliance_report_path, "w", encoding="utf-8") as report_file:
|
585
|
+
report_file.write(generate_compliance_report(file, compliance_feedback))
|
586
|
+
|
587
|
+
click.echo(f"✅ Compliance report generated for {file} -> {compliance_report_path}")
|
588
|
+
|
589
|
+
except Exception as e:
|
590
|
+
logging.error(f"❌ Error processing {file}: {str(e)}")
|
591
|
+
click.echo(f"❌ Error processing {file}: {str(e)}")
|
592
|
+
|
307
593
|
if compliance_issues:
|
308
594
|
for issue in compliance_issues:
|
309
595
|
click.echo(f"⚠️ {issue}")
|
310
596
|
click.echo("✅ Compliance measures have been enforced!")
|
311
597
|
else:
|
312
598
|
click.echo("✅ Code meets all compliance regulations. No changes needed.")
|
313
|
-
|
599
|
+
|
314
600
|
logging.info("Compliance & Regulation Check Completed.")
|
315
601
|
|
316
602
|
def validate_compliance_with_ai(code):
|
317
|
-
"""
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
Return a JSON response with keys: gdpr, ccpa, ai_act, iso_42001, each set to True or False.
|
326
|
-
|
327
|
-
Code:
|
328
|
-
```
|
329
|
-
{code}
|
330
|
-
```
|
331
|
-
"""
|
332
|
-
|
333
|
-
response = openai.ChatCompletion.create(
|
334
|
-
model="gpt-4",
|
335
|
-
messages=[{"role": "system", "content": prompt}]
|
336
|
-
)
|
337
|
-
|
338
|
-
result = response["choices"][0]["message"]["content"]
|
339
|
-
|
340
|
-
try:
|
341
|
-
return json.loads(result)
|
342
|
-
except json.JSONDecodeError:
|
343
|
-
return {"gdpr": False, "ccpa": False, "ai_act": False, "iso_42001": False}
|
603
|
+
"""Analyze code for compliance with GDPR, CCPA, AI Act, and ISO 42001."""
|
604
|
+
return {
|
605
|
+
"gdpr": True,
|
606
|
+
"ccpa": True,
|
607
|
+
"ai_act": False,
|
608
|
+
"iso_42001": False
|
609
|
+
} # Replace with AI-based compliance validation
|
344
610
|
|
345
611
|
def apply_gdpr_compliance(filepath):
|
346
|
-
logging.info(f"
|
612
|
+
logging.info(f"Applying GDPR compliance to {filepath}.")
|
347
613
|
|
348
614
|
def apply_ccpa_compliance(filepath):
|
349
|
-
logging.info(f"
|
615
|
+
logging.info(f"Applying CCPA compliance to {filepath}.")
|
350
616
|
|
351
617
|
def apply_ai_act_compliance(filepath):
|
352
|
-
logging.info(f"
|
618
|
+
logging.info(f"Applying AI Act compliance to {filepath}.")
|
353
619
|
|
354
620
|
def apply_iso_42001_compliance(filepath):
|
355
|
-
logging.info(f"
|
621
|
+
logging.info(f"Applying ISO 42001 AI governance framework to {filepath}.")
|
622
|
+
|
623
|
+
def generate_compliance_report(filepath, feedback):
|
624
|
+
"""Generate a structured compliance report."""
|
625
|
+
return f"""
|
626
|
+
# Compliance Report for {os.path.basename(filepath)}
|
627
|
+
|
628
|
+
## Compliance Status:
|
629
|
+
- **GDPR:** {"✅ Compliant" if feedback.get("gdpr") else "❌ Not Compliant"}
|
630
|
+
- **CCPA:** {"✅ Compliant" if feedback.get("ccpa") else "❌ Not Compliant"}
|
631
|
+
- **AI Act:** {"✅ Compliant" if feedback.get("ai_act") else "❌ Not Compliant"}
|
632
|
+
- **ISO 42001:** {"✅ Compliant" if feedback.get("iso_42001") else "❌ Not Compliant"}
|
633
|
+
|
634
|
+
## Recommendations:
|
635
|
+
- { "Ensure data privacy measures are in place." if not feedback.get("gdpr") else "GDPR compliance verified." }
|
636
|
+
- { "Strengthen consumer rights protection." if not feedback.get("ccpa") else "CCPA compliance verified." }
|
637
|
+
- { "Classify AI system under the AI Act risk framework." if not feedback.get("ai_act") else "AI Act compliance verified." }
|
638
|
+
- { "Align with ISO 42001 AI governance framework." if not feedback.get("iso_42001") else "ISO 42001 compliance verified." }
|
356
639
|
|
640
|
+
---
|
357
641
|
|
358
|
-
|
359
|
-
|
642
|
+
🛠 *Generated by Compliance Checker*
|
643
|
+
"""
|
644
|
+
|
645
|
+
# ✅ Add commands to Maya CLI
|
646
|
+
maya.add_command(is_secured)
|
360
647
|
maya.add_command(check_ethics)
|
361
648
|
maya.add_command(doc)
|
362
649
|
maya.add_command(codex)
|
@@ -366,5 +653,10 @@ maya.add_command(check_best_practices)
|
|
366
653
|
maya.add_command(set_env)
|
367
654
|
maya.add_command(optimize)
|
368
655
|
|
656
|
+
# ✅ Run CLI
|
369
657
|
if __name__ == "__main__":
|
370
|
-
|
658
|
+
try:
|
659
|
+
maya()
|
660
|
+
except Exception as e:
|
661
|
+
logger.exception("Unexpected error: %s", str(e))
|
662
|
+
sys.exit(1)
|
maya_cli/refactor.py
CHANGED
@@ -45,8 +45,8 @@ def write_file(file_path, content):
|
|
45
45
|
except Exception as e:
|
46
46
|
error_msg = f"❌ Error writing {file_path}: {str(e)}"
|
47
47
|
|
48
|
-
|
49
|
-
|
48
|
+
logging.error(error_msg)
|
49
|
+
click.echo(error_msg)
|
50
50
|
|
51
51
|
def refactor_code_with_openai(code):
|
52
52
|
"""Sends code to OpenAI for best-practices refactoring."""
|
@@ -75,15 +75,16 @@ def refactor_code_with_openai(code):
|
|
75
75
|
optimized_code = response["choices"][0]["message"]["content"].strip()
|
76
76
|
logging.debug(f"OpenAI API response received successfully.")
|
77
77
|
return optimized_code
|
78
|
-
except openai.
|
78
|
+
except openai.OpenAIError as e: # Corrected
|
79
79
|
error_msg = f"❌ OpenAI API Error: {str(e)}"
|
80
80
|
except Exception as e:
|
81
81
|
error_msg = f"❌ Unexpected Error: {str(e)}"
|
82
|
-
|
82
|
+
|
83
83
|
logging.error(error_msg)
|
84
84
|
click.echo(error_msg)
|
85
85
|
return code # Return original code if API call fails
|
86
86
|
|
87
|
+
|
87
88
|
def process_directory(directory, filename=None):
|
88
89
|
"""Scans the given directory and refactors specified files."""
|
89
90
|
if not os.path.exists(directory):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: maya-cli
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.4
|
4
4
|
Summary: Maya CLI - AI Project Generator
|
5
5
|
Home-page: https://github.com/anointingmayami/Maya.ai
|
6
6
|
Author: King Anointing Joseph Mayami
|
@@ -26,6 +26,63 @@ Dynamic: summary
|
|
26
26
|
## Overview
|
27
27
|
Maya CLI is a command-line interface (CLI) designed to assist in AI project generation, optimization, security enforcement, and best practices validation. This documentation provides a guide on how to use each CLI command effectively.
|
28
28
|
|
29
|
+
# Quick Guide to Getting Started with Maya AI
|
30
|
+
|
31
|
+
## Step 1: Installation and Setup Development Environment
|
32
|
+
To begin using Maya AI, you need to set up your development environment. Follow these steps:
|
33
|
+
|
34
|
+
1. Ensure you have Python installed (preferably Python 3.8+).
|
35
|
+
2. Install the required dependencies using pip:
|
36
|
+
```sh
|
37
|
+
pip install click python-dotenv openai
|
38
|
+
```
|
39
|
+
3. Clone the Maya AI repository (if applicable) or set up your project directory.
|
40
|
+
|
41
|
+
## Step 2: Set Up OpenAI Key in Environment Variables
|
42
|
+
To integrate OpenAI services, you must configure your API key in an `.env` file:
|
43
|
+
|
44
|
+
1. Create a `.env` file in your project directory.
|
45
|
+
2. Use the `set_env` command to store your OpenAI API key:
|
46
|
+
```sh
|
47
|
+
maya set-env OPENAI_API_KEY your_api_key_here
|
48
|
+
```
|
49
|
+
This command will securely save your key in the `.env` file.
|
50
|
+
|
51
|
+
## Step 3: Create a Maya AI Project
|
52
|
+
Once the environment is set up, you can create a new AI project using the Maya CLI:
|
53
|
+
|
54
|
+
1. Run the following command to create a new project:
|
55
|
+
```sh
|
56
|
+
maya create your_project_name
|
57
|
+
```
|
58
|
+
2. This will generate the necessary project structure for your AI application.
|
59
|
+
3. Navigate into your project directory and start developing.
|
60
|
+
|
61
|
+
## Additional Maya AI CLI Commands
|
62
|
+
- **Check Best Practices:**
|
63
|
+
```sh
|
64
|
+
maya check-best-practices path_to_project
|
65
|
+
```
|
66
|
+
Ensures your project follows AI development best practices.
|
67
|
+
|
68
|
+
- **Optimize a File:**
|
69
|
+
```sh
|
70
|
+
maya optimize parent_folder sub_folder filename
|
71
|
+
```
|
72
|
+
Automatically imports optimization scripts to improve performance.
|
73
|
+
|
74
|
+
- **Check API Security:**
|
75
|
+
```sh
|
76
|
+
maya is-secured parent_folder sub_folder filename
|
77
|
+
```
|
78
|
+
Runs an AI-based security check on your API implementations.
|
79
|
+
|
80
|
+
- **Check Code Ethics:**
|
81
|
+
```sh
|
82
|
+
maya check-ethics parent_folder sub_folder filename
|
83
|
+
```
|
84
|
+
Reviews code for efficiency, accuracy, and ethical standards.
|
85
|
+
|
29
86
|
## Installation
|
30
87
|
Before using Maya CLI, ensure that the required dependencies are installed:
|
31
88
|
```sh
|
@@ -49,27 +106,27 @@ maya create my_ai_project
|
|
49
106
|
### 2. Check Best Practices
|
50
107
|
#### Command:
|
51
108
|
```sh
|
52
|
-
maya
|
109
|
+
maya check-best-practices [folder] [filename]
|
53
110
|
```
|
54
111
|
#### Description:
|
55
112
|
Validates Python code against best practices.
|
56
113
|
|
57
114
|
#### Example:
|
58
115
|
```sh
|
59
|
-
maya
|
116
|
+
maya check-best-practices api my_script.py
|
60
117
|
```
|
61
118
|
|
62
119
|
### 3. Set Environment Variable
|
63
120
|
#### Command:
|
64
121
|
```sh
|
65
|
-
maya
|
122
|
+
maya set-env <key> <value>
|
66
123
|
```
|
67
124
|
#### Description:
|
68
125
|
Sets a key-value pair in the `.env` file.
|
69
126
|
|
70
127
|
#### Example:
|
71
128
|
```sh
|
72
|
-
maya
|
129
|
+
maya set-env OPENAI_API_KEY my_api_key
|
73
130
|
```
|
74
131
|
|
75
132
|
### 4. Optimize AI Scripts
|
@@ -101,14 +158,14 @@ maya isSecured api my_api.py
|
|
101
158
|
### 6. Check Code Ethics
|
102
159
|
#### Command:
|
103
160
|
```sh
|
104
|
-
maya
|
161
|
+
maya check-ethics <target> [filename]
|
105
162
|
```
|
106
163
|
#### Description:
|
107
164
|
Validates code efficiency, accuracy, and best practices.
|
108
165
|
|
109
166
|
#### Example:
|
110
167
|
```sh
|
111
|
-
maya
|
168
|
+
maya check-ethics my_project
|
112
169
|
```
|
113
170
|
|
114
171
|
### 7. Generate Documentation
|
@@ -0,0 +1,11 @@
|
|
1
|
+
maya_cli/__init__.py,sha256=d7ktJFCti7GbZZJJHwTLpLy9EyI3lJmkqtL3YnR-cm8,69
|
2
|
+
maya_cli/cli.py,sha256=XfD_SadKZltJHiuKPkoVwUcHwVgsMuX-MkEi6J3CVUM,25372
|
3
|
+
maya_cli/project_generator.py,sha256=AB9uV_lBe-KPywMJ3uDH9YPSTRHXFP7qzqpPdxDB5GY,2967
|
4
|
+
maya_cli/refactor.py,sha256=ipi3iabQOcyQyJn20PErpgi-Hb4cb8f8p7zW0HO22_s,3890
|
5
|
+
maya_cli/scripts/__init__.py,sha256=yY3Tbs-t4HSl4I0Ev0RcHMnHU7SwljlWRveiRJkeCB8,10
|
6
|
+
maya_cli/scripts/optimize.py,sha256=UqDIHyyYPXZkhAb4GSvjbN0IvwXM2aFnpSh4k0Jzobo,4820
|
7
|
+
maya_cli-0.1.4.dist-info/METADATA,sha256=Y4vy4YBBqodUu67Q4spqEGSGQCyHPbSdiKLJrWpLPwI,5373
|
8
|
+
maya_cli-0.1.4.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
9
|
+
maya_cli-0.1.4.dist-info/entry_points.txt,sha256=K4mI6r7-idKvOmz7zpMpK6HaEnraRoRt4nSW1jTfCgE,43
|
10
|
+
maya_cli-0.1.4.dist-info/top_level.txt,sha256=nZzw8c5hxqres4pU9UUFCTjwBSHUDNjqCTM7yOFnnrE,9
|
11
|
+
maya_cli-0.1.4.dist-info/RECORD,,
|
maya_cli-0.1.2.dist-info/RECORD
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
maya_cli/__init__.py,sha256=d7ktJFCti7GbZZJJHwTLpLy9EyI3lJmkqtL3YnR-cm8,69
|
2
|
-
maya_cli/cli.py,sha256=SuTi2pzEEYPEHSVfVIoi75ts-QHKLFeXYWmUd53tm-s,13859
|
3
|
-
maya_cli/project_generator.py,sha256=AB9uV_lBe-KPywMJ3uDH9YPSTRHXFP7qzqpPdxDB5GY,2967
|
4
|
-
maya_cli/refactor.py,sha256=THX6VBKzFztFKEwjREGehQJaWABJYZ_4LaTHrqr20VE,3877
|
5
|
-
maya_cli/scripts/__init__.py,sha256=yY3Tbs-t4HSl4I0Ev0RcHMnHU7SwljlWRveiRJkeCB8,10
|
6
|
-
maya_cli/scripts/optimize.py,sha256=UqDIHyyYPXZkhAb4GSvjbN0IvwXM2aFnpSh4k0Jzobo,4820
|
7
|
-
maya_cli-0.1.2.dist-info/METADATA,sha256=eYq9N-4CuBM4vawOf2xM-_Pc0u11TlcO2VvB6NATqDg,3469
|
8
|
-
maya_cli-0.1.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
9
|
-
maya_cli-0.1.2.dist-info/entry_points.txt,sha256=K4mI6r7-idKvOmz7zpMpK6HaEnraRoRt4nSW1jTfCgE,43
|
10
|
-
maya_cli-0.1.2.dist-info/top_level.txt,sha256=nZzw8c5hxqres4pU9UUFCTjwBSHUDNjqCTM7yOFnnrE,9
|
11
|
-
maya_cli-0.1.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|