Coverage for mindsdb / api / http / namespaces / skills.py: 96%
88 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
1from http import HTTPStatus
3from flask import request
4from flask_restx import Resource
6from mindsdb.metrics.metrics import api_endpoint_metrics
7from mindsdb.api.http.namespaces.configs.projects import ns_conf
8from mindsdb.api.http.utils import http_error
9from mindsdb.interfaces.skills.skills_controller import SkillsController
10from mindsdb.utilities.exception import EntityNotExistsError
13def create_skill(project_name, skill):
14 skills_controller = SkillsController()
15 for required_field in ['name', 'type', 'params']:
16 if required_field not in skill:
17 return http_error(
18 HTTPStatus.BAD_REQUEST,
19 'Missing field',
20 'Missing "{}" field for skill'.format(required_field)
21 )
22 name = skill['name']
23 type = skill['type']
24 params = skill['params']
26 try:
27 existing_skill = skills_controller.get_skill(name, project_name)
28 except ValueError:
29 # Project needs to exist
30 return http_error(
31 HTTPStatus.NOT_FOUND,
32 'Project not found',
33 f'Project with name {project_name} does not exist'
34 )
36 if existing_skill is not None: 36 ↛ 37line 36 didn't jump to line 37 because the condition on line 36 was never true
37 return http_error(
38 HTTPStatus.CONFLICT,
39 'Skill already exists',
40 f'Skill with name {name} already exists. Please use a different name'
41 )
43 new_skill = skills_controller.add_skill(name, project_name, type, params)
44 return new_skill.as_dict(), HTTPStatus.CREATED
47@ns_conf.route('/<project_name>/skills')
48class SkillsResource(Resource):
49 @ns_conf.doc('list_skills')
50 @api_endpoint_metrics('GET', '/skills')
51 def get(self, project_name):
52 ''' List all skills'''
53 skills_controller = SkillsController()
54 try:
55 all_skills = skills_controller.get_skills(project_name)
56 except EntityNotExistsError:
57 # Project needs to exist.
58 return http_error(
59 HTTPStatus.NOT_FOUND,
60 'Project not found',
61 f'Project with name {project_name} does not exist'
62 )
63 return [skill.as_dict() for skill in all_skills]
65 @ns_conf.doc('create_skill')
66 @api_endpoint_metrics('POST', '/skills')
67 def post(self, project_name):
68 '''Create a skill'''
70 # Check required request format.
71 if 'skill' not in request.json:
72 return http_error(
73 HTTPStatus.BAD_REQUEST,
74 'Missing parameter',
75 'Must provide "skill" parameter in POST body'
76 )
77 skill = request.json['skill']
78 return create_skill(project_name, skill)
81@ns_conf.route('/<project_name>/skills/<skill_name>')
82@ns_conf.param('project_name', 'Name of the project')
83@ns_conf.param('skill_name', 'Name of the skill')
84class SkillResource(Resource):
85 @ns_conf.doc('get_skill')
86 @api_endpoint_metrics('GET', '/skills/skill')
87 def get(self, project_name, skill_name):
88 '''Gets a skill by name'''
89 skills_controller = SkillsController()
90 try:
91 existing_skill = skills_controller.get_skill(skill_name, project_name)
92 except EntityNotExistsError:
93 # Project needs to exist
94 return http_error(
95 HTTPStatus.NOT_FOUND,
96 'Project not found',
97 f'Project with name {project_name} does not exist'
98 )
100 if existing_skill is None:
101 return http_error(
102 HTTPStatus.NOT_FOUND,
103 'Skill not found',
104 f'Skill with name {skill_name} not found.'
105 )
106 return existing_skill.as_dict()
108 @ns_conf.doc('update_skill')
109 @api_endpoint_metrics('PUT', '/skills/skill')
110 def put(self, project_name, skill_name):
111 '''Updates a skill by name, creating one if it doesn't exist'''
112 skills_controller = SkillsController()
114 # Check required request format.
115 if 'skill' not in request.json:
116 return http_error(
117 HTTPStatus.BAD_REQUEST,
118 'Missing parameter',
119 'Must provide "skill" parameter in POST body'
120 )
122 try:
123 existing_skill = skills_controller.get_skill(skill_name, project_name)
124 except EntityNotExistsError:
125 # Project needs to exist
126 return http_error(
127 HTTPStatus.NOT_FOUND,
128 'Project not found',
129 f'Project with name {project_name} does not exist'
130 )
132 skill = request.json['skill']
133 if existing_skill is None:
134 # Use same name as provided in URL.
135 skill['name'] = skill_name
136 return create_skill(project_name, skill)
138 new_name = skill.get('name', None)
139 new_type = skill.get('type', None)
140 new_params = skill.get('params', None)
141 updated_skill = skills_controller.update_skill(
142 skill_name,
143 new_name=new_name,
144 project_name=project_name,
145 type=new_type,
146 params=new_params)
147 return updated_skill.as_dict()
149 @ns_conf.doc('delete_skill')
150 @api_endpoint_metrics('DELETE', '/skills/skill')
151 def delete(self, project_name, skill_name):
152 '''Deletes a skill by name'''
153 skills_controller = SkillsController()
154 try:
155 existing_skill = skills_controller.get_skill(skill_name, project_name)
156 except EntityNotExistsError:
157 # Project needs to exist
158 return http_error(
159 HTTPStatus.NOT_FOUND,
160 'Project not found',
161 f'Project with name {project_name} does not exist'
162 )
164 if existing_skill is None:
165 return http_error(
166 HTTPStatus.NOT_FOUND,
167 'Skill not found',
168 f'Skill with name {skill_name} not found.'
169 )
170 skills_controller.delete_skill(skill_name, project_name)
171 return '', HTTPStatus.NO_CONTENT