weaviate-cli 2.1.3.dev1__tar.gz → 2.2.0__tar.gz
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.
- weaviate-cli-2.2.0/LICENSE +27 -0
- weaviate-cli-2.2.0/PKG-INFO +59 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/README.rst +1 -1
- weaviate-cli-2.2.0/cli.py +29 -0
- weaviate-cli-2.2.0/semi/classification/commands.py +161 -0
- weaviate-cli-2.2.0/semi/config/commands.py +214 -0
- weaviate-cli-2.2.0/semi/data/__init__.py +0 -0
- weaviate-cli-2.1.3.dev1/semi/commands/data.py → weaviate-cli-2.2.0/semi/data/commands.py +54 -30
- weaviate-cli-2.2.0/semi/misc.py +68 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/semi/prompt.py +8 -5
- weaviate-cli-2.2.0/semi/schema/__init__.py +0 -0
- weaviate-cli-2.2.0/semi/schema/commands.py +117 -0
- weaviate-cli-2.2.0/semi/utils.py +39 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/semi/version.py +1 -1
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/setup.py +9 -3
- weaviate-cli-2.2.0/weaviate_cli.egg-info/PKG-INFO +59 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/weaviate_cli.egg-info/SOURCES.txt +10 -6
- weaviate-cli-2.2.0/weaviate_cli.egg-info/entry_points.txt +2 -0
- weaviate-cli-2.2.0/weaviate_cli.egg-info/requires.txt +3 -0
- weaviate-cli-2.1.3.dev1/PKG-INFO +0 -61
- weaviate-cli-2.1.3.dev1/cli.py +0 -127
- weaviate-cli-2.1.3.dev1/semi/commands/misc.py +0 -26
- weaviate-cli-2.1.3.dev1/semi/commands/schema.py +0 -68
- weaviate-cli-2.1.3.dev1/semi/config/configuration.py +0 -87
- weaviate-cli-2.1.3.dev1/semi/config/manage.py +0 -50
- weaviate-cli-2.1.3.dev1/weaviate_cli.egg-info/PKG-INFO +0 -61
- weaviate-cli-2.1.3.dev1/weaviate_cli.egg-info/entry_points.txt +0 -4
- weaviate-cli-2.1.3.dev1/weaviate_cli.egg-info/requires.txt +0 -2
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/semi/__init__.py +0 -0
- {weaviate-cli-2.1.3.dev1/semi/commands → weaviate-cli-2.2.0/semi/classification}/__init__.py +0 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/semi/config/__init__.py +0 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/semi/config/config_values.py +0 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/setup.cfg +0 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/weaviate_cli.egg-info/dependency_links.txt +0 -0
- {weaviate-cli-2.1.3.dev1 → weaviate-cli-2.2.0}/weaviate_cli.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Copyright (c) 2021, SeMI Technologies B.V.
|
|
2
|
+
All rights reserved.
|
|
3
|
+
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
|
6
|
+
|
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
8
|
+
list of conditions and the following disclaimer.
|
|
9
|
+
|
|
10
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
11
|
+
this list of conditions and the following disclaimer in the documentation
|
|
12
|
+
and/or other materials provided with the distribution.
|
|
13
|
+
|
|
14
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
15
|
+
contributors may be used to endorse or promote products derived from
|
|
16
|
+
this software without specific prior written permission.
|
|
17
|
+
|
|
18
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
19
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
20
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
21
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
22
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
23
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
24
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
25
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
26
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
27
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: weaviate-cli
|
|
3
|
+
Version: 2.2.0
|
|
4
|
+
Summary: Comand line interface to interact with weaviate
|
|
5
|
+
Author: SeMI Technologies
|
|
6
|
+
Author-email: hello@semi.technology
|
|
7
|
+
Requires-Python: >=3.6
|
|
8
|
+
Description-Content-Type: text/x-rst
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
|
|
11
|
+
Weaviate CLI
|
|
12
|
+
============
|
|
13
|
+
.. image:: https://raw.githubusercontent.com/semi-technologies/weaviate/19de0956c69b66c5552447e84d016f4fe29d12c9/docs/assets/weaviate-logo.png
|
|
14
|
+
:width: 180
|
|
15
|
+
:align: right
|
|
16
|
+
:alt: Weaviate logo
|
|
17
|
+
|
|
18
|
+
.. image:: https://travis-ci.com/semi-technologies/weaviate-cli.svg?branch=master
|
|
19
|
+
:target: https://travis-ci.com/semi-technologies/weaviate-cli
|
|
20
|
+
:alt: Build Status (Travis CI)
|
|
21
|
+
|
|
22
|
+
.. image:: https://badge.fury.io/py/weaviate-cli.svg
|
|
23
|
+
:target: https://badge.fury.io/py/weaviate-cli
|
|
24
|
+
:alt: PyPI version
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
**Command Line Interface (CLI) tool for interacting with a Weaviate instance directly from your Terminal**
|
|
28
|
+
|
|
29
|
+
Visit the official `SeMi Technology <https://weaviate.io/>`_ website for more information about the Weaviate and how to use it in production.
|
|
30
|
+
|
|
31
|
+
Check out our `weaviate-client <https://pypi.org/project/weaviate-client/>`_ library for interacting with a Weaviate instance using python.
|
|
32
|
+
|
|
33
|
+
Installation
|
|
34
|
+
------------
|
|
35
|
+
|
|
36
|
+
| Install using: ``pip install weaviate-cli``
|
|
37
|
+
| Run using: ``weaviate --help``
|
|
38
|
+
|
|
39
|
+
Articles
|
|
40
|
+
--------
|
|
41
|
+
|
|
42
|
+
Here are some articles on weaviate:
|
|
43
|
+
|
|
44
|
+
- `Semantic Search Queries Return More Informed Results <https://hackernoon.com/semantic-search-queries-return-more-informed-results-nr5335nw>`_
|
|
45
|
+
- `Getting Started with Weaviate Python Library <https://towardsdatascience.com/getting-started-with-weaviate-python-client-e85d14f19e4f>`_
|
|
46
|
+
- `A sub-50ms neural search with DistilBERT and Weaviate <https://towardsdatascience.com/a-sub-50ms-neural-search-with-distilbert-and-weaviate-4857ae390154>`_
|
|
47
|
+
- `SeMI Technology Medium blogs <https://medium.com/semi-technologies>`_
|
|
48
|
+
|
|
49
|
+
Support
|
|
50
|
+
-------
|
|
51
|
+
|
|
52
|
+
- Use our `Slack Channel <https://join.slack.com/t/weaviate/shared_invite/zt-goaoifjr-o8FuVz9b1HLzhlUfyfddhw>`_ for support or any other question.
|
|
53
|
+
- Use the ``weaviate`` tag on `Stackoverflow <https://stackoverflow.com/questions/tagged/weaviate>`_ for questions.
|
|
54
|
+
- For bugs and/or problems with the package submit a Github `issue <https://github.com/semi-technologies/weaviate-python-client/issues>`_.
|
|
55
|
+
|
|
56
|
+
Contributing
|
|
57
|
+
------------
|
|
58
|
+
|
|
59
|
+
- Do you want to contribute to `Weaviate`, read `How to Contribute <https://github.com/semi-technologies/weaviate/blob/master/CONTRIBUTE.md>`_.
|
|
@@ -16,7 +16,7 @@ Weaviate CLI
|
|
|
16
16
|
|
|
17
17
|
**Command Line Interface (CLI) tool for interacting with a Weaviate instance directly from your Terminal**
|
|
18
18
|
|
|
19
|
-
Visit the official `SeMi Technology <https://
|
|
19
|
+
Visit the official `SeMi Technology <https://weaviate.io/>`_ website for more information about the Weaviate and how to use it in production.
|
|
20
20
|
|
|
21
21
|
Check out our `weaviate-client <https://pypi.org/project/weaviate-client/>`_ library for interacting with a Weaviate instance using python.
|
|
22
22
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from semi.config.commands import Configuration, config_group
|
|
3
|
+
from semi.data.commands import data_group
|
|
4
|
+
from semi.schema.commands import schema_group
|
|
5
|
+
from semi.classification.commands import classification_group
|
|
6
|
+
from semi.misc import main_init, main_ping, main_version
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.group()
|
|
10
|
+
@click.pass_context
|
|
11
|
+
@click.option('--config-file', required=False, default=None, type=str, is_flag=False,
|
|
12
|
+
help="If specified cli uses the config specified with this path.")
|
|
13
|
+
def main(ctx: click.Context, config_file):
|
|
14
|
+
ctx.obj = {
|
|
15
|
+
"config": Configuration(config_file)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
main.add_command(config_group)
|
|
20
|
+
main.add_command(data_group)
|
|
21
|
+
main.add_command(schema_group)
|
|
22
|
+
main.add_command(classification_group)
|
|
23
|
+
main.add_command(main_ping)
|
|
24
|
+
main.add_command(main_version)
|
|
25
|
+
main.add_command(main_init)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if __name__ == "__main__":
|
|
29
|
+
main()
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Weaviate CLI classification group functions.
|
|
3
|
+
"""
|
|
4
|
+
import json
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from semi.utils import get_client_from_context
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.group('classify')
|
|
11
|
+
@click.pass_context
|
|
12
|
+
def classification_group(ctx : click.Context):
|
|
13
|
+
"""
|
|
14
|
+
Classification of data.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
ctx.obj["classification"] = get_classification_from_ctx(ctx)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@classification_group.command('get')
|
|
21
|
+
@click.pass_context
|
|
22
|
+
@click.argument('classification_id')
|
|
23
|
+
def get_classification(ctx, classification_id):
|
|
24
|
+
"""
|
|
25
|
+
Get a classification info by id.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
show_classification_info(ctx.obj["classification"], classification_id)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@classification_group.command('status')
|
|
32
|
+
@click.pass_context
|
|
33
|
+
@click.argument('classification_id')
|
|
34
|
+
def get_classification_status(ctx, classification_id):
|
|
35
|
+
"""
|
|
36
|
+
Get a classification status by id.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
show_classification_status(ctx.obj["classification"], classification_id)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# TODO: Accept array input
|
|
43
|
+
@classification_group.command('start')
|
|
44
|
+
@click.pass_context
|
|
45
|
+
@click.option('--class-name', required = True, type = str,
|
|
46
|
+
help = "Object type to classify")
|
|
47
|
+
@click.option('--based-on', required = True, type = str,
|
|
48
|
+
help = "Properties to base classification on")
|
|
49
|
+
@click.option('--property', required = True, type = str,
|
|
50
|
+
help = "Properties to classify")
|
|
51
|
+
@click.option('-k', '--k', required = False, type = int,
|
|
52
|
+
help = "Use kNN classification with value k")
|
|
53
|
+
def start_classification(ctx, class_name, based_on, property, k):
|
|
54
|
+
"""
|
|
55
|
+
Start a classification.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
if k:
|
|
59
|
+
start_knn_classification(ctx.obj["classification"], class_name,
|
|
60
|
+
[based_on], [property], k)
|
|
61
|
+
else:
|
|
62
|
+
start_contextionary_classification(ctx.obj["classification"], class_name,
|
|
63
|
+
[based_on], [property])
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
####################################################################################################
|
|
67
|
+
# Helper functions
|
|
68
|
+
####################################################################################################
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def show_classification_status(classification, classification_id : str):
|
|
72
|
+
"""
|
|
73
|
+
Get a classification status by id.
|
|
74
|
+
|
|
75
|
+
Parameters
|
|
76
|
+
----------
|
|
77
|
+
classification : Classification
|
|
78
|
+
Classification client.
|
|
79
|
+
classification_id : str
|
|
80
|
+
Classification id.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
if classification.is_running(classification_id):
|
|
84
|
+
click.echo("Classification is running.")
|
|
85
|
+
elif classification.is_failed(classification_id):
|
|
86
|
+
click.echo("Classification failed.")
|
|
87
|
+
elif classification.is_complete(classification_id):
|
|
88
|
+
click.echo("Classification is complete.")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def show_classification_info(classification, classification_id : str):
|
|
92
|
+
"""
|
|
93
|
+
Get a classification info by id.
|
|
94
|
+
|
|
95
|
+
Parameters
|
|
96
|
+
----------
|
|
97
|
+
classification : Classification
|
|
98
|
+
Classification client.
|
|
99
|
+
classification_id : str
|
|
100
|
+
Classification id.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
result = classification.get(classification_id)
|
|
104
|
+
click.echo(json.dumps(result, indent=4))
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def start_contextionary_classification(classification, class_name : str, based_on : list, properties : list):
|
|
108
|
+
"""
|
|
109
|
+
Start a contextionary classification.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
classification : Classification
|
|
114
|
+
Classification client.
|
|
115
|
+
class_name : str
|
|
116
|
+
Object type to classify.
|
|
117
|
+
based_on : list
|
|
118
|
+
Properties to base classification on.
|
|
119
|
+
properties : list
|
|
120
|
+
Properties to classify.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
result = classification.schedule()\
|
|
124
|
+
.with_type("text2vec-contextionary-contextual")\
|
|
125
|
+
.with_class_name(class_name)\
|
|
126
|
+
.with_based_on_properties(based_on)\
|
|
127
|
+
.with_classify_properties(properties)\
|
|
128
|
+
.do()
|
|
129
|
+
show_classification_info(classification, result['id'])
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def start_knn_classification(classification, class_name : str, based_on : list, properties : list, k : int):
|
|
133
|
+
"""
|
|
134
|
+
Start a kNN classification.
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
classification : Classification
|
|
139
|
+
Classification client.
|
|
140
|
+
class_name : str
|
|
141
|
+
Object type to classify.
|
|
142
|
+
based_on : list
|
|
143
|
+
Properties to base classification on.
|
|
144
|
+
properties : list
|
|
145
|
+
Properties to classify.
|
|
146
|
+
k : int
|
|
147
|
+
kNN value.
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
result = classification.schedule()\
|
|
151
|
+
.with_type("knn")\
|
|
152
|
+
.with_class_name(class_name)\
|
|
153
|
+
.with_based_on_properties(based_on)\
|
|
154
|
+
.with_classify_properties(properties)\
|
|
155
|
+
.with_settings({'k':k})\
|
|
156
|
+
.do()
|
|
157
|
+
show_classification_info(classification, result['id'])
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_classification_from_ctx(ctx : click.Context):
|
|
161
|
+
return get_client_from_context(ctx).classification
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Weaviate CLI config group functions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional
|
|
10
|
+
from getpass import getpass
|
|
11
|
+
|
|
12
|
+
import click
|
|
13
|
+
import requests
|
|
14
|
+
import weaviate
|
|
15
|
+
from semi.prompt import let_user_pick
|
|
16
|
+
import semi.config.config_values as cfg_vals
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@click.group("config")
|
|
20
|
+
def config_group():
|
|
21
|
+
"""
|
|
22
|
+
Configuration of the CLI.
|
|
23
|
+
"""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@config_group.command("view")
|
|
28
|
+
@click.pass_context
|
|
29
|
+
def config_view(ctx):
|
|
30
|
+
"""
|
|
31
|
+
Print the current CLI configuration.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
print(ctx.obj["config"])
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@config_group.command("set")
|
|
38
|
+
@click.pass_context
|
|
39
|
+
def config_set(ctx):
|
|
40
|
+
"""
|
|
41
|
+
Set a new CLI configuration.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
ctx.obj["config"].create_new_config()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
####################################################################################################
|
|
48
|
+
# Helper class
|
|
49
|
+
####################################################################################################
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class Configuration:
|
|
53
|
+
default_file_path = ".config/semi_technologies/"
|
|
54
|
+
default_file_name = "configs.json"
|
|
55
|
+
|
|
56
|
+
def __init__(self, config_file: Optional[str] = None):
|
|
57
|
+
"""
|
|
58
|
+
Initialize a configuration instance.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
config_file : str or None
|
|
63
|
+
The path to the user specified configuration file.
|
|
64
|
+
"""
|
|
65
|
+
if config_file:
|
|
66
|
+
assert os.path.isfile(config_file), "Config file does not exist!"
|
|
67
|
+
self.config_path = config_file
|
|
68
|
+
with open(self.config_path, 'r', encoding="utf-8") as config_data:
|
|
69
|
+
try:
|
|
70
|
+
self.config = json.load(config_data)
|
|
71
|
+
except:
|
|
72
|
+
click.echo("Fatal Error: Config file is not valid JSON!")
|
|
73
|
+
sys.exit(1)
|
|
74
|
+
|
|
75
|
+
else:
|
|
76
|
+
self.config_path = Path(os.path.join(os.getenv("HOME"),
|
|
77
|
+
self.default_file_path,
|
|
78
|
+
self.default_file_name))
|
|
79
|
+
self.config_path.touch(exist_ok=True)
|
|
80
|
+
with open(self.config_path, 'r', encoding="utf-8") as configuration_file:
|
|
81
|
+
try:
|
|
82
|
+
self.config = json.load(configuration_file)
|
|
83
|
+
except:
|
|
84
|
+
click.echo("No existing configuration found, creating new one.")
|
|
85
|
+
self.create_new_config()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_client(self) -> weaviate.Client:
|
|
89
|
+
"""
|
|
90
|
+
Get a weaviate client from the configuration.
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
weaviate.Client
|
|
95
|
+
A weaviate client.
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
if self.config["auth"] is None:
|
|
100
|
+
return weaviate.Client(self.config["url"])
|
|
101
|
+
if self.config["auth"]["type"] == cfg_vals.config_value_auth_type_client_secret:
|
|
102
|
+
cred = weaviate.AuthClientCredentials(self.config["auth"]["secret"])
|
|
103
|
+
return weaviate.Client(self.config["url"], cred)
|
|
104
|
+
if self.config["auth"]["type"] == cfg_vals.config_value_auth_type_username_pass:
|
|
105
|
+
cred = weaviate.AuthClientPassword(self.config["auth"]["user"], self.config["auth"]["pass"])
|
|
106
|
+
return weaviate.Client(self.config["url"], cred)
|
|
107
|
+
except requests.exceptions.ConnectionError:
|
|
108
|
+
click.echo("Fatal Error: Could not connect to the weaviate instance!")
|
|
109
|
+
sys.exit(1)
|
|
110
|
+
except KeyError:
|
|
111
|
+
click.echo("Fatal Error: Unknown authentication type in config!")
|
|
112
|
+
sys.exit(1)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def create_new_config(self):
|
|
116
|
+
"""
|
|
117
|
+
Create a new configuration (interacitve).
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
self.config = {
|
|
121
|
+
"url": input("Please give a weaviate url: "),
|
|
122
|
+
"auth": self.get_authentication_config()
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
self.write_config(self.config)
|
|
126
|
+
|
|
127
|
+
print("Config creation complete\n")
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@classmethod
|
|
131
|
+
def write_config(cls, configuration: dict):
|
|
132
|
+
"""
|
|
133
|
+
Write a configuration to the config file.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
configuration : dict
|
|
138
|
+
The configuration to write.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
config_path = Path(os.path.join(os.getenv("HOME"),
|
|
142
|
+
cls.default_file_path,
|
|
143
|
+
cls.default_file_name))
|
|
144
|
+
|
|
145
|
+
with open(config_path, 'w', encoding="utf-8") as configuration_file:
|
|
146
|
+
json.dump(configuration, configuration_file)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@classmethod
|
|
150
|
+
def create_user_specified_config(cls, url: str, user: str, password: str, client_secret: str):
|
|
151
|
+
"""
|
|
152
|
+
Create a configuration from user specified values.
|
|
153
|
+
|
|
154
|
+
Parameters
|
|
155
|
+
----------
|
|
156
|
+
url : str
|
|
157
|
+
The weaviate url.
|
|
158
|
+
user : str
|
|
159
|
+
The user name.
|
|
160
|
+
password : str
|
|
161
|
+
The user password.
|
|
162
|
+
client_secret : str
|
|
163
|
+
The client secret.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
if user and password:
|
|
167
|
+
auth = {
|
|
168
|
+
"type": cfg_vals.config_value_auth_type_username_pass,
|
|
169
|
+
"user": user,
|
|
170
|
+
"pass": password
|
|
171
|
+
}
|
|
172
|
+
elif client_secret:
|
|
173
|
+
auth = {
|
|
174
|
+
"type": cfg_vals.config_value_auth_type_client_secret,
|
|
175
|
+
"secret": client_secret
|
|
176
|
+
}
|
|
177
|
+
else:
|
|
178
|
+
auth = None
|
|
179
|
+
|
|
180
|
+
config = {
|
|
181
|
+
"url": url,
|
|
182
|
+
"auth": auth
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
cls.write_config(config)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def get_authentication_config(self) -> Optional[dict]:
|
|
189
|
+
"""
|
|
190
|
+
Get the authentication configuration.
|
|
191
|
+
|
|
192
|
+
Returns
|
|
193
|
+
-------
|
|
194
|
+
dict
|
|
195
|
+
The authentication configuration.
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
auth_options = ["No authentication", "Client secret", "Username and password"]
|
|
199
|
+
selection_index = let_user_pick(auth_options, "Please select the authentication method:")
|
|
200
|
+
if selection_index == 1:
|
|
201
|
+
return {
|
|
202
|
+
"type": cfg_vals.config_value_auth_type_client_secret,
|
|
203
|
+
"secret": getpass("Please specify the client secret: ")
|
|
204
|
+
}
|
|
205
|
+
if selection_index == 2:
|
|
206
|
+
return {
|
|
207
|
+
"type": cfg_vals.config_value_auth_type_username_pass,
|
|
208
|
+
"user": input("Please specify the user name: "),
|
|
209
|
+
"pass": getpass("Please specify the user password: ")
|
|
210
|
+
}
|
|
211
|
+
return None
|
|
212
|
+
|
|
213
|
+
def __str__(self):
|
|
214
|
+
return str(json.dumps(self.config, indent=4))
|
|
File without changes
|
|
@@ -1,15 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
"""
|
|
2
|
+
Weaviate CLI data group functions.
|
|
3
|
+
"""
|
|
4
|
+
|
|
2
5
|
import sys
|
|
6
|
+
import json
|
|
7
|
+
import click
|
|
3
8
|
import weaviate
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if VERSION_2:
|
|
7
|
-
from weaviate.tools import Batcher
|
|
8
|
-
from semi.config.configuration import Configuration
|
|
9
|
+
|
|
10
|
+
from semi.utils import get_client_from_context
|
|
9
11
|
from semi.prompt import is_question_answer_yes
|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
@click.group("data", help="Data object manipulation in weaviate.")
|
|
15
|
+
def data_group():
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@data_group.command("import", help="Import data from json file.")
|
|
20
|
+
@click.pass_context
|
|
21
|
+
@click.argument('file')
|
|
22
|
+
@click.option('--fail-on-error', required=False, default=False, is_flag=True, help="Fail if entity loading throws an error")
|
|
23
|
+
def concept_import(ctx, file, fail_on_error):
|
|
24
|
+
import_data_from_file(get_client_from_context(ctx), file, fail_on_error)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@data_group.command("delete", help="Delete all data objects in weaviate.")
|
|
28
|
+
@click.pass_context
|
|
29
|
+
@click.option('--force', required=False, default=False, is_flag=True)
|
|
30
|
+
def data_empty(ctx, force):
|
|
31
|
+
delete_all_data(get_client_from_context(ctx), force)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
####################################################################################################
|
|
35
|
+
# Helper functions
|
|
36
|
+
####################################################################################################
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def delete_all_data(client: weaviate.Client, force: bool) -> None:
|
|
13
40
|
"""
|
|
14
41
|
Delete all weaviate objects.
|
|
15
42
|
|
|
@@ -22,11 +49,11 @@ def delete_all_data(cfg: Configuration, force: bool) -> None:
|
|
|
22
49
|
"""
|
|
23
50
|
|
|
24
51
|
if force:
|
|
25
|
-
_delete_all(
|
|
52
|
+
_delete_all(client)
|
|
26
53
|
sys.exit(0)
|
|
27
54
|
if not is_question_answer_yes("Do you really want to delete all data?"):
|
|
28
55
|
sys.exit(0)
|
|
29
|
-
_delete_all(
|
|
56
|
+
_delete_all(client)
|
|
30
57
|
|
|
31
58
|
|
|
32
59
|
def _delete_all(client: weaviate.Client):
|
|
@@ -44,7 +71,7 @@ def _delete_all(client: weaviate.Client):
|
|
|
44
71
|
client.schema.create(schema)
|
|
45
72
|
|
|
46
73
|
|
|
47
|
-
def import_data_from_file(
|
|
74
|
+
def import_data_from_file(client: weaviate.Client, file: str, fail_on_error: bool) -> None:
|
|
48
75
|
"""
|
|
49
76
|
Import data from a file.
|
|
50
77
|
|
|
@@ -58,10 +85,15 @@ def import_data_from_file(cfg: Configuration, file: str, fail_on_error: bool) ->
|
|
|
58
85
|
If True exits at the first error, if False prints the error only.
|
|
59
86
|
"""
|
|
60
87
|
|
|
61
|
-
importer = DataFileImporter(
|
|
88
|
+
importer = DataFileImporter(client, file, fail_on_error)
|
|
62
89
|
importer.load()
|
|
63
90
|
|
|
64
91
|
|
|
92
|
+
####################################################################################################
|
|
93
|
+
# DataFileImporter
|
|
94
|
+
####################################################################################################
|
|
95
|
+
|
|
96
|
+
|
|
65
97
|
class DataFileImporter:
|
|
66
98
|
|
|
67
99
|
def __init__(self, client: weaviate.Client, data_path: str, fail_on_error: bool):
|
|
@@ -80,17 +112,12 @@ class DataFileImporter:
|
|
|
80
112
|
|
|
81
113
|
self.client = client
|
|
82
114
|
self.fail_on_error = fail_on_error
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
else:
|
|
90
|
-
self.batcher = client.batch(
|
|
91
|
-
batch_size=512,
|
|
92
|
-
callback=self._exit_on_error,
|
|
93
|
-
)
|
|
115
|
+
|
|
116
|
+
self.batcher = client.batch(
|
|
117
|
+
batch_size=512,
|
|
118
|
+
callback=self._exit_on_error,
|
|
119
|
+
)
|
|
120
|
+
|
|
94
121
|
with open(data_path, 'r') as data_io:
|
|
95
122
|
self.data = json.load(data_io)
|
|
96
123
|
|
|
@@ -126,10 +153,7 @@ class DataFileImporter:
|
|
|
126
153
|
self.batcher.add_data_object(**obj)
|
|
127
154
|
for ref in vasd.data_references:
|
|
128
155
|
self.batcher.add_reference(**ref)
|
|
129
|
-
|
|
130
|
-
self.batcher.close()
|
|
131
|
-
else:
|
|
132
|
-
self.batcher.flush()
|
|
156
|
+
self.batcher.flush()
|
|
133
157
|
|
|
134
158
|
class ValidateAndSplitData:
|
|
135
159
|
|
|
@@ -151,9 +175,9 @@ class ValidateAndSplitData:
|
|
|
151
175
|
self.data_references = []
|
|
152
176
|
|
|
153
177
|
def validate_and_split(self) -> None:
|
|
154
|
-
"""
|
|
178
|
+
"""
|
|
155
179
|
Go through the entire data and validate it against a schema
|
|
156
|
-
if not valid exit with error, if valid split it into the
|
|
180
|
+
if not valid exit with error, if valid split it into the
|
|
157
181
|
primitive object and the references.
|
|
158
182
|
"""
|
|
159
183
|
|
|
@@ -216,7 +240,7 @@ def dissect_reference(refs: list, from_class: str, from_id: str, from_prop: str)
|
|
|
216
240
|
refs : list
|
|
217
241
|
A list of references to be dissected.
|
|
218
242
|
from_class : str
|
|
219
|
-
The object's class name.
|
|
243
|
+
The object's class name.
|
|
220
244
|
from_id : str
|
|
221
245
|
The id of the object.
|
|
222
246
|
from_prop : str
|
|
@@ -242,7 +266,7 @@ def dissect_reference(refs: list, from_class: str, from_id: str, from_prop: str)
|
|
|
242
266
|
|
|
243
267
|
|
|
244
268
|
def dissect_schema(schema: dict) -> dict:
|
|
245
|
-
"""
|
|
269
|
+
"""
|
|
246
270
|
Dissect the schema into a dict listing all classes with their name as key to have faster
|
|
247
271
|
validation access.
|
|
248
272
|
|