Skip to content

Commit de7297a

Browse files
author
Arvid Paeglit
committed
splitted CLI commands
started login process
1 parent 001ca3a commit de7297a

4 files changed

Lines changed: 127 additions & 17 deletions

File tree

‎deepcode/auth.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import asyncio
2+
3+
from .connection import api_call, SOURCE
4+
5+
async def login(service_url):
6+
"""
7+
Initiate a new login protocal.
8+
User will be forwarded to Deepcode website to complete the process.
9+
"""
10+
res = await api_call('login', method="POST", data={'source': SOURCE})
11+
api_key, login_url = res['sessionToken'], res['loginURL']
12+
13+

‎deepcode/cli.py‎

Lines changed: 106 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import click
2+
import json
23
import asyncio
34
import aiohttp
45
import os.path
@@ -7,10 +8,98 @@
78

89
from . import analize_folders, analize_git
910
from .utils import logger
11+
from .auth import login
1012
from .git_utils import parse_git_uri
13+
from .connection import DEFAULT_SERVICE_URL
1114

1215
format_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+
14103
class 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)

‎deepcode/connection.py‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
from .utils import logger
1010

11-
# API_TOKEN = '1eea7e6a02f82252a71732401eb2f6b3711f2db306e0bf88c3e50fd2b640fe79'
12-
API_TOKEN = 'd9f5eb73e28d31bdc65d3eed3df165b16ac078477d0fa4749db2e8a5df5d499f'
11+
# API_KEY = '1eea7e6a02f82252a71732401eb2f6b3711f2db306e0bf88c3e50fd2b640fe79'
12+
# API_KEY = 'd9f5eb73e28d31bdc65d3eed3df165b16ac078477d0fa4749db2e8a5df5d499f' # localhost
1313

1414
DEFAULT_SERVICE_URL = 'https://www.deepcode.ai'
1515
NETWORK_RETRY_DELAY = 5
16+
SOURCE = 'CLI'
1617

1718
# BACKEND_STATUS_CODES = {
1819
# 'success': 200,
@@ -41,11 +42,13 @@ async def wrapper(*args, **kwargs):
4142

4243
@reconnect
4344
async def api_call(path, method='GET', data=None, extra_headers={}, callback=lambda resp: resp.json(), compression_level=6):
44-
SERVICE_URL = os.environ.get('SERVICE_URL', DEFAULT_SERVICE_URL)
45+
SERVICE_URL = os.environ.get('DEEPCODE_SERVICE_URL', '') or DEFAULT_SERVICE_URL
46+
API_KEY = os.environ.get('DEEPCODE_API_KEY', '')
47+
4548
url = urljoin(urljoin(SERVICE_URL, '/publicapi/'), path)
4649

4750
default_headers = {
48-
'Session-Token': API_TOKEN,
51+
'Session-Token': API_KEY,
4952
}
5053

5154
if data:

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ tqdm = "^4.42.1"
3939
pytest = "^5.2"
4040

4141
[tool.poetry.scripts]
42-
deepcode = 'deepcode.cli:process'
42+
deepcode = 'deepcode.cli:main'
4343

4444
[build-system]
4545
requires = ["poetry>=0.12"]

0 commit comments

Comments
 (0)