11import click
2+ import json
23import asyncio
34import aiohttp
45import os .path
78
89from . import analize_folders , analize_git
910from .utils import logger
11+ from .auth import login
1012from .git_utils import parse_git_uri
13+ from .connection import DEFAULT_SERVICE_URL
1114
1215format_txt = lambda r : print (r )
1316
17+ CONFIG_FILE_PATH = '~/.deepcode.json'
18+
19+ def _save_config (service_url , api_key , config_file ):
20+ data = {
21+ 'service_url' : service_url ,
22+ 'api_key' : api_key ,
23+ }
24+ data = {k :v for k ,v in data .items () if v }
25+
26+ with open (config_file , 'w' ) as cfg :
27+ cfg .write (json .dumps (data ))
28+
29+
30+ @click .group ()
31+ @click .option ('--service-url' , '-s' , 'service_url' ,
32+ default = lambda : os .environ .get ('DEEPCODE_SERVICE_URL' , '' ),
33+ help = "Custom DeepCode service URL (e.g. {})" .format (DEFAULT_SERVICE_URL ))
34+ @click .option ('--api-key' , '-a' , 'api_key' ,
35+ default = lambda : os .environ .get ('DEEPCODE_API_KEY' , '' ),
36+ help = "Deepcode API key" )
37+ @click .option (
38+ '--config-file' , '-c' ,
39+ type = click .Path (dir_okay = False ),
40+ default = CONFIG_FILE_PATH ,
41+ help = "Config file (default: {})" .format (CONFIG_FILE_PATH )
42+ )
43+ @click .pass_context
44+ def main (ctx , service_url , api_key , config_file ):
45+ """
46+ A tool, that detects bugs and quality issues in JavaScript, TypeScript, Python and Java..
47+ It uses a mighty engine based on AI from Deepcode.
48+ """
49+
50+ filename = os .path .expanduser (config_file )
51+
52+ config_data = {}
53+ if (not service_url or not api_key ) and os .path .exists (filename ):
54+ with open (filename ) as cfg :
55+ config_data = json .loads (cfg .read ())
56+
57+ ctx .obj = {
58+ 'service_url' : service_url or config_data .get ('service_url' , '' ),
59+ 'api_key' : api_key or config_data .get ('api_key' , '' ),
60+ 'config_file' : filename
61+ }
62+
63+
64+ @main .command ()
65+ @click .pass_context
66+ def config (ctx ):
67+ """
68+ Store configuration values in a file.
69+ """
70+
71+ service_url = click .prompt (
72+ "Please enter Deepcode Service URL (or leave it blank to use {})" .format (DEFAULT_SERVICE_URL ),
73+ default = ctx .obj .get ('service_url' , '' )
74+ )
75+
76+ api_key = click .prompt (
77+ "Please enter your API key" ,
78+ default = ctx .obj .get ('api_key' , '' )
79+ )
80+
81+ _save_config (service_url , api_key , ctx .obj ['config_file' ])
82+
83+
84+ @main .command ()
85+ @click .pass_context
86+ def login (ctx ):
87+ """
88+ Initiate a new login protocal.
89+ User will be forwarded to Deepcode website to complete the process.
90+ """
91+
92+ service_url = ctx .obj .get ('service_url' , '' )
93+
94+ async def task (service_url ):
95+ api_key = await login (service_url )
96+
97+ _save_config (service_url , api_key , ctx .obj ['config_file' ])
98+
99+ loop = asyncio .get_event_loop ()
100+ loop .run_until_complete (task )
101+
102+
14103class GitURI (click .ParamType ):
15104 name = 'Remote'
16105
@@ -25,30 +114,35 @@ def convert(self, value, param, ctx):
25114
26115 return data
27116
28-
29- @click .command ()
117+ @main .command ()
30118@optgroup .group ('Source location' ,
31119 cls = RequiredMutuallyExclusiveOptionGroup ,
32120 help = 'The configuration of repository location' )
33121@optgroup .option ("--path" , "-p" , "paths" ,
34122 multiple = True ,
35123 type = click .Path (exists = True , file_okay = False , dir_okay = True , readable = True , resolve_path = True ),
36- help = "Path to folder to be processed." )
124+ help = "Path to folder to be processed. Multiple paths are allowed " )
37125@optgroup .option ("--git-uri" , "-r" , "remote_params" ,
38126 type = GitURI (),
39127 help = "Git URI (e.g. git@<platform>:<owner>/<repo>.git@<oid> or https://<platform>/<owner>/<repo>.git@<oid>)" ,
40128)
41- @optgroup .group ('Environment configuration' , help = 'The configuration of environment' )
42- @optgroup .option ('--linters' , is_flag = True , help = "Enable linters" )
43- @optgroup .option ('--service-url' , help = "Custom DeepCode service URL (e.g. https://www.deepcode.ai)" )
44- @click .option ('--logging' , '-l' , 'logging_level' , default = 'error' ,
129+ @click .option ('--linters' , '-l' , 'linters_enabled' , is_flag = True , help = "Enable linters" )
130+ @click .option ('--logging' , '-log' , 'logging_level' , default = 'error' ,
45131 type = click .Choice (['debug' , 'info' , 'warning' , 'error' , 'critical' ], case_sensitive = False ))
46132@click .option ('--format' , default = 'json' ,
47133 type = click .Choice (['txt' , 'json' ], case_sensitive = False ))
48- def process (linters , service_url , paths , remote_params , logging_level , format ):
49- # TODO: support multiple paths
134+ @click .pass_context
135+ def analyze (ctx , linters_enabled , paths , remote_params , logging_level , format ):
136+ """
137+ Analyzes your code using Deepcode AI engine.
138+ """
139+ service_url = ctx .obj .get ('service_url' , '' )
50140 if service_url :
51- os .environ ['SERVICE_URL' ] = service_url
141+ os .environ ['DEEPCODE_SERVICE_URL' ] = service_url
142+
143+ api_key = ctx .obj .get ('api_key' , '' )
144+ if api_key :
145+ os .environ ['DEEPCODE_API_KEY' ] = api_key
52146
53147 if logging_level :
54148 logging_levels = {
@@ -76,9 +170,9 @@ async def runner(func, *args, **kwargs):
76170
77171 if paths :
78172 paths = [os .path .abspath (p ) for p in paths ]
79- task = runner (analize_folders , paths = paths , linters_enabled = linters )
173+ task = runner (analize_folders , paths = paths , linters_enabled = linters_enabled )
80174 else :
81- task = runner (analize_git , linters_enabled = linters , ** remote_params )
175+ task = runner (analize_git , linters_enabled = linters_enabled , ** remote_params )
82176
83177 loop = asyncio .get_event_loop ()
84178 loop .run_until_complete (task )
0 commit comments