pixeltable 0.1.2__py3-none-any.whl → 0.2.0__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.
Potentially problematic release.
This version of pixeltable might be problematic. Click here for more details.
- pixeltable/__init__.py +21 -4
- pixeltable/catalog/__init__.py +13 -0
- pixeltable/catalog/catalog.py +159 -0
- pixeltable/catalog/column.py +200 -0
- pixeltable/catalog/dir.py +32 -0
- pixeltable/catalog/globals.py +33 -0
- pixeltable/catalog/insertable_table.py +191 -0
- pixeltable/catalog/named_function.py +36 -0
- pixeltable/catalog/path.py +58 -0
- pixeltable/catalog/path_dict.py +139 -0
- pixeltable/catalog/schema_object.py +39 -0
- pixeltable/catalog/table.py +581 -0
- pixeltable/catalog/table_version.py +749 -0
- pixeltable/catalog/table_version_path.py +133 -0
- pixeltable/catalog/view.py +203 -0
- pixeltable/client.py +520 -31
- pixeltable/dataframe.py +540 -349
- pixeltable/env.py +373 -48
- pixeltable/exceptions.py +12 -21
- pixeltable/exec/__init__.py +9 -0
- pixeltable/exec/aggregation_node.py +78 -0
- pixeltable/exec/cache_prefetch_node.py +113 -0
- pixeltable/exec/component_iteration_node.py +79 -0
- pixeltable/exec/data_row_batch.py +95 -0
- pixeltable/exec/exec_context.py +22 -0
- pixeltable/exec/exec_node.py +61 -0
- pixeltable/exec/expr_eval_node.py +217 -0
- pixeltable/exec/in_memory_data_node.py +69 -0
- pixeltable/exec/media_validation_node.py +43 -0
- pixeltable/exec/sql_scan_node.py +225 -0
- pixeltable/exprs/__init__.py +24 -0
- pixeltable/exprs/arithmetic_expr.py +102 -0
- pixeltable/exprs/array_slice.py +71 -0
- pixeltable/exprs/column_property_ref.py +77 -0
- pixeltable/exprs/column_ref.py +105 -0
- pixeltable/exprs/comparison.py +77 -0
- pixeltable/exprs/compound_predicate.py +98 -0
- pixeltable/exprs/data_row.py +187 -0
- pixeltable/exprs/expr.py +586 -0
- pixeltable/exprs/expr_set.py +39 -0
- pixeltable/exprs/function_call.py +380 -0
- pixeltable/exprs/globals.py +69 -0
- pixeltable/exprs/image_member_access.py +115 -0
- pixeltable/exprs/image_similarity_predicate.py +58 -0
- pixeltable/exprs/inline_array.py +107 -0
- pixeltable/exprs/inline_dict.py +101 -0
- pixeltable/exprs/is_null.py +38 -0
- pixeltable/exprs/json_mapper.py +121 -0
- pixeltable/exprs/json_path.py +159 -0
- pixeltable/exprs/literal.py +54 -0
- pixeltable/exprs/object_ref.py +41 -0
- pixeltable/exprs/predicate.py +44 -0
- pixeltable/exprs/row_builder.py +355 -0
- pixeltable/exprs/rowid_ref.py +94 -0
- pixeltable/exprs/type_cast.py +53 -0
- pixeltable/exprs/variable.py +45 -0
- pixeltable/func/__init__.py +9 -0
- pixeltable/func/aggregate_function.py +194 -0
- pixeltable/func/batched_function.py +53 -0
- pixeltable/func/callable_function.py +69 -0
- pixeltable/func/expr_template_function.py +82 -0
- pixeltable/func/function.py +110 -0
- pixeltable/func/function_registry.py +227 -0
- pixeltable/func/globals.py +36 -0
- pixeltable/func/nos_function.py +202 -0
- pixeltable/func/signature.py +166 -0
- pixeltable/func/udf.py +163 -0
- pixeltable/functions/__init__.py +52 -103
- pixeltable/functions/eval.py +216 -0
- pixeltable/functions/fireworks.py +61 -0
- pixeltable/functions/huggingface.py +120 -0
- pixeltable/functions/image.py +16 -0
- pixeltable/functions/openai.py +88 -0
- pixeltable/functions/pil/image.py +148 -7
- pixeltable/functions/string.py +13 -0
- pixeltable/functions/together.py +27 -0
- pixeltable/functions/util.py +41 -0
- pixeltable/functions/video.py +62 -0
- pixeltable/iterators/__init__.py +3 -0
- pixeltable/iterators/base.py +48 -0
- pixeltable/iterators/document.py +311 -0
- pixeltable/iterators/video.py +89 -0
- pixeltable/metadata/__init__.py +54 -0
- pixeltable/metadata/converters/convert_10.py +18 -0
- pixeltable/metadata/schema.py +211 -0
- pixeltable/plan.py +656 -0
- pixeltable/store.py +413 -182
- pixeltable/tests/conftest.py +143 -86
- pixeltable/tests/test_audio.py +65 -0
- pixeltable/tests/test_catalog.py +27 -0
- pixeltable/tests/test_client.py +14 -14
- pixeltable/tests/test_component_view.py +372 -0
- pixeltable/tests/test_dataframe.py +433 -0
- pixeltable/tests/test_dirs.py +78 -62
- pixeltable/tests/test_document.py +117 -0
- pixeltable/tests/test_exprs.py +591 -135
- pixeltable/tests/test_function.py +297 -67
- pixeltable/tests/test_functions.py +283 -1
- pixeltable/tests/test_migration.py +43 -0
- pixeltable/tests/test_nos.py +54 -0
- pixeltable/tests/test_snapshot.py +208 -0
- pixeltable/tests/test_table.py +1086 -258
- pixeltable/tests/test_transactional_directory.py +42 -0
- pixeltable/tests/test_types.py +5 -11
- pixeltable/tests/test_video.py +149 -34
- pixeltable/tests/test_view.py +530 -0
- pixeltable/tests/utils.py +186 -45
- pixeltable/tool/create_test_db_dump.py +149 -0
- pixeltable/type_system.py +490 -133
- pixeltable/utils/__init__.py +17 -46
- pixeltable/utils/clip.py +12 -15
- pixeltable/utils/coco.py +136 -0
- pixeltable/utils/documents.py +39 -0
- pixeltable/utils/filecache.py +195 -0
- pixeltable/utils/help.py +11 -0
- pixeltable/utils/media_store.py +76 -0
- pixeltable/utils/parquet.py +126 -0
- pixeltable/utils/pytorch.py +172 -0
- pixeltable/utils/s3.py +13 -0
- pixeltable/utils/sql.py +17 -0
- pixeltable/utils/transactional_directory.py +35 -0
- pixeltable-0.2.0.dist-info/LICENSE +18 -0
- pixeltable-0.2.0.dist-info/METADATA +117 -0
- pixeltable-0.2.0.dist-info/RECORD +125 -0
- {pixeltable-0.1.2.dist-info → pixeltable-0.2.0.dist-info}/WHEEL +1 -1
- pixeltable/catalog.py +0 -1421
- pixeltable/exprs.py +0 -1745
- pixeltable/function.py +0 -269
- pixeltable/functions/clip.py +0 -10
- pixeltable/functions/pil/__init__.py +0 -23
- pixeltable/functions/tf.py +0 -21
- pixeltable/index.py +0 -57
- pixeltable/tests/test_dict.py +0 -24
- pixeltable/tests/test_tf.py +0 -69
- pixeltable/tf.py +0 -33
- pixeltable/utils/tf.py +0 -33
- pixeltable/utils/video.py +0 -32
- pixeltable-0.1.2.dist-info/LICENSE +0 -201
- pixeltable-0.1.2.dist-info/METADATA +0 -89
- pixeltable-0.1.2.dist-info/RECORD +0 -37
pixeltable/tests/conftest.py
CHANGED
|
@@ -1,118 +1,175 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
import pathlib
|
|
5
|
+
from typing import List
|
|
4
6
|
|
|
7
|
+
import numpy as np
|
|
5
8
|
import pytest
|
|
6
9
|
|
|
7
|
-
import pixeltable as
|
|
10
|
+
import pixeltable as pxt
|
|
8
11
|
import pixeltable.catalog as catalog
|
|
9
|
-
from pixeltable
|
|
10
|
-
|
|
11
|
-
from pixeltable.
|
|
12
|
+
from pixeltable import exprs
|
|
13
|
+
from pixeltable import functions as ptf
|
|
14
|
+
from pixeltable.exprs import RELATIVE_PATH_ROOT as R
|
|
15
|
+
from pixeltable.metadata import SystemInfo, create_system_info
|
|
16
|
+
from pixeltable.metadata.schema import TableSchemaVersion, TableVersion, Table, Function, Dir
|
|
17
|
+
from pixeltable.tests.utils import read_data_file, create_test_tbl, create_all_datatypes_tbl, skip_test_if_not_installed
|
|
18
|
+
from pixeltable.type_system import StringType, ImageType, FloatType
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
@pytest.fixture(scope='session')
|
|
15
|
-
def
|
|
22
|
+
def init_env(tmp_path_factory) -> None:
|
|
16
23
|
from pixeltable.env import Env
|
|
24
|
+
# set the relevant env vars for Client() to connect to the test db
|
|
25
|
+
|
|
26
|
+
shared_home = pathlib.Path(os.environ.get('PIXELTABLE_HOME', '~/.pixeltable')).expanduser()
|
|
27
|
+
home_dir = str(tmp_path_factory.mktemp('base') / '.pixeltable')
|
|
28
|
+
os.environ['PIXELTABLE_HOME'] = home_dir
|
|
29
|
+
os.environ['PIXELTABLE_CONFIG'] = str(shared_home / 'config.yaml')
|
|
30
|
+
test_db = 'test'
|
|
31
|
+
os.environ['PIXELTABLE_DB'] = test_db
|
|
32
|
+
os.environ['PIXELTABLE_PGDATA'] = str(shared_home / 'pgdata')
|
|
33
|
+
|
|
17
34
|
# this also runs create_all()
|
|
18
|
-
Env.get().set_up(
|
|
35
|
+
Env.get().set_up(echo=True)
|
|
19
36
|
yield
|
|
20
37
|
# leave db in place for debugging purposes
|
|
21
38
|
|
|
39
|
+
@pytest.fixture(scope='function')
|
|
40
|
+
def test_client(init_env) -> pxt.Client:
|
|
41
|
+
# Clean the DB *before* instantiating a client object. This is because some tests
|
|
42
|
+
# (such as test_migration.py) may leave the DB in a broken state, from which the
|
|
43
|
+
# client is uninstantiable.
|
|
44
|
+
clean_db()
|
|
45
|
+
cl = pxt.Client(reload=True)
|
|
46
|
+
cl.logging(level=logging.DEBUG, to_stdout=True)
|
|
47
|
+
yield cl
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def clean_db(restore_tables: bool = True) -> None:
|
|
51
|
+
from pixeltable.env import Env
|
|
52
|
+
# The logic from Client.reset_catalog() has been moved here, so that it
|
|
53
|
+
# does not rely on instantiating a Client object. As before, UUID-named data tables will
|
|
54
|
+
# not be cleaned. If in the future it is desirable to clean out data tables as well,
|
|
55
|
+
# the commented lines may be used to drop ALL tables from the test db.
|
|
56
|
+
# sql_md = declarative_base().metadata
|
|
57
|
+
# sql_md.reflect(Env.get().engine)
|
|
58
|
+
# sql_md.drop_all(bind=Env.get().engine)
|
|
59
|
+
engine = Env.get().engine
|
|
60
|
+
SystemInfo.__table__.drop(engine, checkfirst=True)
|
|
61
|
+
TableSchemaVersion.__table__.drop(engine, checkfirst=True)
|
|
62
|
+
TableVersion.__table__.drop(engine, checkfirst=True)
|
|
63
|
+
Table.__table__.drop(engine, checkfirst=True)
|
|
64
|
+
Function.__table__.drop(engine, checkfirst=True)
|
|
65
|
+
Dir.__table__.drop(engine, checkfirst=True)
|
|
66
|
+
if restore_tables:
|
|
67
|
+
Dir.__table__.create(engine)
|
|
68
|
+
Function.__table__.create(engine)
|
|
69
|
+
Table.__table__.create(engine)
|
|
70
|
+
TableVersion.__table__.create(engine)
|
|
71
|
+
TableSchemaVersion.__table__.create(engine)
|
|
72
|
+
SystemInfo.__table__.create(engine)
|
|
73
|
+
create_system_info(engine)
|
|
74
|
+
|
|
22
75
|
|
|
23
76
|
@pytest.fixture(scope='function')
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
db = cl.create_db(f'test')
|
|
27
|
-
yield db
|
|
28
|
-
cl.drop_db(db.name, force=True)
|
|
77
|
+
def test_tbl(test_client: pxt.Client) -> catalog.Table:
|
|
78
|
+
return create_test_tbl(test_client)
|
|
29
79
|
|
|
80
|
+
# @pytest.fixture(scope='function')
|
|
81
|
+
# def test_stored_fn(test_client: pt.Client) -> pt.Function:
|
|
82
|
+
# @pt.udf(return_type=pt.IntType(), param_types=[pt.IntType()])
|
|
83
|
+
# def test_fn(x):
|
|
84
|
+
# return x + 1
|
|
85
|
+
# test_client.create_function('test_fn', test_fn)
|
|
86
|
+
# return test_fn
|
|
30
87
|
|
|
31
88
|
@pytest.fixture(scope='function')
|
|
32
|
-
def test_tbl
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
89
|
+
def test_tbl_exprs(test_tbl: catalog.Table) -> List[exprs.Expr]:
|
|
90
|
+
#def test_tbl_exprs(test_tbl: catalog.Table, test_stored_fn: pt.Function) -> List[exprs.Expr]:
|
|
91
|
+
|
|
92
|
+
t = test_tbl
|
|
93
|
+
return [
|
|
94
|
+
t.c1,
|
|
95
|
+
t.c7['*'].f1,
|
|
96
|
+
exprs.Literal('test'),
|
|
97
|
+
exprs.InlineDict({
|
|
98
|
+
'a': t.c1, 'b': t.c6.f1, 'c': 17,
|
|
99
|
+
'd': exprs.InlineDict({'e': t.c2}),
|
|
100
|
+
'f': exprs.InlineArray((t.c3, t.c3))
|
|
101
|
+
}),
|
|
102
|
+
exprs.InlineArray([[t.c2, t.c2], [t.c2, t.c2]]),
|
|
103
|
+
t.c2 > 5,
|
|
104
|
+
t.c2 == None,
|
|
105
|
+
~(t.c2 > 5),
|
|
106
|
+
(t.c2 > 5) & (t.c1 == 'test'),
|
|
107
|
+
(t.c2 > 5) | (t.c1 == 'test'),
|
|
108
|
+
t.c7['*'].f5 >> [R[3], R[2], R[1], R[0]],
|
|
109
|
+
t.c8[0, 1:],
|
|
110
|
+
t.c2.astype(FloatType()),
|
|
111
|
+
(t.c2 + 1).astype(FloatType()),
|
|
112
|
+
t.c2.apply(str),
|
|
113
|
+
(t.c2 + 1).apply(str),
|
|
114
|
+
t.c3.apply(str),
|
|
115
|
+
t.c4.apply(str),
|
|
116
|
+
t.c5.apply(str),
|
|
117
|
+
t.c6.apply(str),
|
|
118
|
+
t.c1.apply(json.loads),
|
|
119
|
+
t.c8.errortype,
|
|
120
|
+
t.c8.errormsg,
|
|
121
|
+
ptf.sum(t.c2, group_by=t.c4, order_by=t.c3),
|
|
122
|
+
#test_stored_fn(t.c2),
|
|
41
123
|
]
|
|
42
|
-
t = test_db.create_table('test__tbl', cols)
|
|
43
|
-
|
|
44
|
-
num_rows = 100
|
|
45
|
-
d1 = {
|
|
46
|
-
'f1': 'test string 1',
|
|
47
|
-
'f2': 1,
|
|
48
|
-
'f3': 1.0,
|
|
49
|
-
'f4': True,
|
|
50
|
-
'f5': [1.0, 2.0, 3.0, 4.0],
|
|
51
|
-
'f6': {
|
|
52
|
-
'f7': 'test string 2',
|
|
53
|
-
'f8': [1.0, 2.0, 3.0, 4.0],
|
|
54
|
-
},
|
|
55
|
-
}
|
|
56
|
-
d2 = [d1, d1]
|
|
57
|
-
|
|
58
|
-
c1_data = [f'test string {i}' for i in range(num_rows)]
|
|
59
|
-
c2_data = [i for i in range(num_rows)]
|
|
60
|
-
c3_data = [float(i) for i in range(num_rows)]
|
|
61
|
-
c4_data = [bool(i % 2) for i in range(num_rows)]
|
|
62
|
-
c5_data = [datetime.datetime.now()] * num_rows
|
|
63
|
-
c6_data = []
|
|
64
|
-
for i in range(num_rows):
|
|
65
|
-
d = {
|
|
66
|
-
'f1': f'test string {i}',
|
|
67
|
-
'f2': i,
|
|
68
|
-
'f3': float(i),
|
|
69
|
-
'f4': bool(i % 2),
|
|
70
|
-
'f5': [1.0, 2.0, 3.0, 4.0],
|
|
71
|
-
'f6': {
|
|
72
|
-
'f7': 'test string 2',
|
|
73
|
-
'f8': [1.0, 2.0, 3.0, 4.0],
|
|
74
|
-
},
|
|
75
|
-
}
|
|
76
|
-
c6_data.append(d)
|
|
77
|
-
|
|
78
|
-
c7_data = [d2] * num_rows
|
|
79
|
-
data = {'c1': c1_data, 'c2': c2_data, 'c3': c3_data, 'c4': c4_data, 'c5': c5_data, 'c6': c6_data, 'c7': c7_data}
|
|
80
|
-
pd_df = pd.DataFrame(data=data)
|
|
81
|
-
t.insert_pandas(pd_df)
|
|
82
|
-
return t
|
|
83
124
|
|
|
125
|
+
@pytest.fixture(scope='function')
|
|
126
|
+
def all_datatypes_tbl(test_client: pxt.Client) -> catalog.Table:
|
|
127
|
+
return create_all_datatypes_tbl(test_client)
|
|
84
128
|
|
|
85
129
|
@pytest.fixture(scope='function')
|
|
86
|
-
def img_tbl(
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
130
|
+
def img_tbl(test_client: pxt.Client) -> catalog.Table:
|
|
131
|
+
schema = {
|
|
132
|
+
'img': ImageType(nullable=False),
|
|
133
|
+
'category': StringType(nullable=False),
|
|
134
|
+
'split': StringType(nullable=False),
|
|
135
|
+
}
|
|
92
136
|
# this table is not indexed in order to avoid the cost of computing embeddings
|
|
93
|
-
tbl =
|
|
94
|
-
|
|
95
|
-
tbl.
|
|
137
|
+
tbl = test_client.create_table('test_img_tbl', schema)
|
|
138
|
+
rows = read_data_file('imagenette2-160', 'manifest.csv', ['img'])
|
|
139
|
+
tbl.insert(rows)
|
|
96
140
|
return tbl
|
|
97
141
|
|
|
142
|
+
@pytest.fixture(scope='function')
|
|
143
|
+
def img_tbl_exprs(img_tbl: catalog.Table) -> List[exprs.Expr]:
|
|
144
|
+
img_t = img_tbl
|
|
145
|
+
return [
|
|
146
|
+
img_t.img.width,
|
|
147
|
+
img_t.img.rotate(90),
|
|
148
|
+
# we're using a list here, not a tuple; the latter turns into a list during the back/forth conversion
|
|
149
|
+
img_t.img.rotate(90).resize([224, 224]),
|
|
150
|
+
img_t.img.fileurl,
|
|
151
|
+
img_t.img.localpath,
|
|
152
|
+
]
|
|
98
153
|
|
|
99
154
|
# TODO: why does this not work with a session scope? (some user tables don't get created with create_all())
|
|
100
155
|
#@pytest.fixture(scope='session')
|
|
101
|
-
#def indexed_img_tbl(
|
|
156
|
+
#def indexed_img_tbl(init_env: None) -> catalog.Table:
|
|
102
157
|
# cl = pt.Client()
|
|
103
158
|
# db = cl.create_db('test_indexed')
|
|
104
159
|
@pytest.fixture(scope='function')
|
|
105
|
-
def indexed_img_tbl(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
160
|
+
def indexed_img_tbl(test_client: pxt.Client) -> catalog.Table:
|
|
161
|
+
skip_test_if_not_installed('nos')
|
|
162
|
+
cl = test_client
|
|
163
|
+
schema = {
|
|
164
|
+
'img': { 'type': ImageType(nullable=False), 'indexed': True },
|
|
165
|
+
'category': StringType(nullable=False),
|
|
166
|
+
'split': StringType(nullable=False),
|
|
167
|
+
}
|
|
168
|
+
tbl = cl.create_table('test_indexed_img_tbl', schema)
|
|
169
|
+
rows = read_data_file('imagenette2-160', 'manifest.csv', ['img'])
|
|
170
|
+
# select output_rows randomly in the hope of getting a good sample of the available categories
|
|
115
171
|
rng = np.random.default_rng(17)
|
|
116
|
-
idxs = rng.choice(np.arange(len(
|
|
117
|
-
|
|
172
|
+
idxs = rng.choice(np.arange(len(rows)), size=40, replace=False)
|
|
173
|
+
rows = [rows[i] for i in idxs]
|
|
174
|
+
tbl.insert(rows)
|
|
118
175
|
return tbl
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
import av
|
|
4
|
+
|
|
5
|
+
import pixeltable as pxt
|
|
6
|
+
import pixeltable.env as env
|
|
7
|
+
from pixeltable.tests.utils import get_video_files, get_audio_files
|
|
8
|
+
from pixeltable.type_system import VideoType, AudioType
|
|
9
|
+
from pixeltable.utils.media_store import MediaStore
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestAudio:
|
|
13
|
+
def check_audio_params(self, path: str, format: Optional[str] = None, codec: Optional[str] = None):
|
|
14
|
+
with av.open(path) as container:
|
|
15
|
+
audio_stream = container.streams.audio[0]
|
|
16
|
+
if format is not None:
|
|
17
|
+
assert format == container.format.name
|
|
18
|
+
if codec is not None:
|
|
19
|
+
assert codec == audio_stream.codec_context.codec.name
|
|
20
|
+
|
|
21
|
+
def test_basic(self, test_client: pxt.Client) -> None:
|
|
22
|
+
audio_filepaths = get_audio_files()
|
|
23
|
+
cl = test_client
|
|
24
|
+
audio_t = cl.create_table('audio', {'audio_file': AudioType()})
|
|
25
|
+
status = audio_t.insert({'audio_file': p} for p in audio_filepaths)
|
|
26
|
+
assert status.num_rows == len(audio_filepaths)
|
|
27
|
+
assert status.num_excs == 0
|
|
28
|
+
paths = audio_t.select(output=audio_t.audio_file.localpath).collect()['output']
|
|
29
|
+
assert set(paths) == set(audio_filepaths)
|
|
30
|
+
|
|
31
|
+
def test_extract(self, test_client: pxt.Client) -> None:
|
|
32
|
+
video_filepaths = get_video_files()
|
|
33
|
+
cl = test_client
|
|
34
|
+
video_t = cl.create_table('videos', {'video': VideoType()})
|
|
35
|
+
from pixeltable.functions.video import extract_audio
|
|
36
|
+
video_t.add_column(audio=extract_audio(video_t.video))
|
|
37
|
+
|
|
38
|
+
# one of the 3 videos doesn't have audio
|
|
39
|
+
status = video_t.insert({'video': p} for p in video_filepaths)
|
|
40
|
+
assert status.num_rows == len(video_filepaths)
|
|
41
|
+
assert status.num_excs == 0
|
|
42
|
+
assert MediaStore.count(video_t.get_id()) == len(video_filepaths) - 1
|
|
43
|
+
assert video_t.where(video_t.audio != None).count() == len(video_filepaths) - 1
|
|
44
|
+
assert env.Env.get().num_tmp_files() == 0
|
|
45
|
+
|
|
46
|
+
# make sure everything works with a fresh client
|
|
47
|
+
cl = pxt.Client()
|
|
48
|
+
video_t = cl.get_table('videos')
|
|
49
|
+
assert video_t.where(video_t.audio != None).count() == len(video_filepaths) - 1
|
|
50
|
+
|
|
51
|
+
# test generating different formats and codecs
|
|
52
|
+
paths = video_t.select(output=extract_audio(video_t.video, format='wav', codec='pcm_s16le')).collect()['output']
|
|
53
|
+
# media files that are created as a part of a query end up in the tmp dir
|
|
54
|
+
assert env.Env.get().num_tmp_files() == video_t.where(video_t.audio != None).count()
|
|
55
|
+
for path in [p for p in paths if p is not None]:
|
|
56
|
+
self.check_audio_params(path, format='wav', codec='pcm_s16le')
|
|
57
|
+
# higher resolution
|
|
58
|
+
paths = video_t.select(output=extract_audio(video_t.video, format='wav', codec='pcm_s32le')).collect()['output']
|
|
59
|
+
for path in [p for p in paths if p is not None]:
|
|
60
|
+
self.check_audio_params(path, format='wav', codec='pcm_s32le')
|
|
61
|
+
|
|
62
|
+
for format in ['mp3', 'flac']:
|
|
63
|
+
paths = video_t.select(output=extract_audio(video_t.video, format=format)).collect()['output']
|
|
64
|
+
for path in [p for p in paths if p is not None]:
|
|
65
|
+
self.check_audio_params(path, format=format)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from pixeltable.catalog import is_valid_identifier, is_valid_path
|
|
2
|
+
|
|
3
|
+
class TestCatalog:
|
|
4
|
+
"""Tests for miscellanous catalog functions."""
|
|
5
|
+
def test_valid_identifier(self) -> None:
|
|
6
|
+
valid_ids = ['a', 'a1', 'a_1', 'a_']
|
|
7
|
+
invalid_ids = ['', '_', '__', '_a', '1a', 'a.b', '.a', 'a-b']
|
|
8
|
+
for valid_id in valid_ids:
|
|
9
|
+
assert is_valid_identifier(valid_id), valid_ids
|
|
10
|
+
|
|
11
|
+
for invalid_id in invalid_ids:
|
|
12
|
+
assert not is_valid_identifier(invalid_id), invalid_ids
|
|
13
|
+
|
|
14
|
+
def test_valid_path(self) -> None:
|
|
15
|
+
assert is_valid_path('', empty_is_valid=True)
|
|
16
|
+
assert not is_valid_path('', empty_is_valid=False)
|
|
17
|
+
|
|
18
|
+
valid_paths = ['a', 'a_.b_', 'a.b.c', 'a.b.c.d']
|
|
19
|
+
invalid_paths = ['.', '..', 'a.', '.a', 'a..b']
|
|
20
|
+
|
|
21
|
+
for valid_path in valid_paths:
|
|
22
|
+
assert is_valid_path(valid_path, empty_is_valid=False), valid_path
|
|
23
|
+
assert is_valid_path(valid_path, empty_is_valid=True), valid_path
|
|
24
|
+
|
|
25
|
+
for invalid_path in invalid_paths:
|
|
26
|
+
assert not is_valid_path(invalid_path, empty_is_valid=False), invalid_path
|
|
27
|
+
assert not is_valid_path(invalid_path, empty_is_valid=True), invalid_path
|
pixeltable/tests/test_client.py
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
import pixeltable as
|
|
4
|
-
|
|
3
|
+
import pixeltable as pxt
|
|
4
|
+
import pixeltable.exceptions as excs
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class TestClient:
|
|
8
|
-
def
|
|
9
|
-
cl =
|
|
10
|
-
_ = cl.
|
|
11
|
-
|
|
12
|
-
_ = cl.create_db('test')
|
|
8
|
+
def test_list_functions(self, init_env) -> None:
|
|
9
|
+
cl = pxt.Client()
|
|
10
|
+
_ = cl.list_functions()
|
|
11
|
+
print(_)
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
def test_drop_table(self, test_tbl: pxt.Table) -> None:
|
|
14
|
+
cl = pxt.Client()
|
|
15
|
+
t = cl.get_table('test_tbl')
|
|
16
|
+
cl.drop_table('test_tbl')
|
|
17
|
+
with pytest.raises(excs.Error):
|
|
18
|
+
_ = cl.get_table('test_tbl')
|
|
19
|
+
with pytest.raises(excs.Error):
|
|
20
|
+
_ = t.show(1)
|
|
21
21
|
|