pixeltable 0.2.26__py3-none-any.whl → 0.2.28__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/__version__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # These version placeholders will be replaced during build.
2
- __version__ = "0.2.26"
3
- __version_tuple__ = (0, 2, 26)
2
+ __version__ = "0.2.28"
3
+ __version_tuple__ = (0, 2, 28)
pixeltable/env.py CHANGED
@@ -496,6 +496,7 @@ class Env:
496
496
  self.__register_package('datasets')
497
497
  self.__register_package('fiftyone')
498
498
  self.__register_package('fireworks', library_name='fireworks-ai')
499
+ self.__register_package('google.generativeai', library_name='google-generativeai')
499
500
  self.__register_package('huggingface_hub', library_name='huggingface-hub')
500
501
  self.__register_package('label_studio_sdk', library_name='label-studio-sdk')
501
502
  self.__register_package('llama_cpp', library_name='llama-cpp-python')
@@ -520,8 +521,14 @@ class Env:
520
521
  self.__register_package('yolox', library_name='git+https://github.com/Megvii-BaseDetection/YOLOX@ac58e0a')
521
522
 
522
523
  def __register_package(self, package_name: str, library_name: Optional[str] = None) -> None:
524
+ is_installed: bool
525
+ try:
526
+ is_installed = importlib.util.find_spec(package_name) is not None
527
+ except ModuleNotFoundError:
528
+ # This can happen if the parent of `package_name` is not installed.
529
+ is_installed = False
523
530
  self.__optional_packages[package_name] = PackageInfo(
524
- is_installed=importlib.util.find_spec(package_name) is not None,
531
+ is_installed=is_installed,
525
532
  library_name=library_name or package_name # defaults to package_name unless specified otherwise
526
533
  )
527
534
 
pixeltable/exprs/expr.py CHANGED
@@ -190,6 +190,7 @@ class Expr(abc.ABC):
190
190
  return new.copy()
191
191
  for i in range(len(self.components)):
192
192
  self.components[i] = self.components[i].substitute(spec)
193
+ self.id = self._create_id()
193
194
  return self
194
195
 
195
196
  @classmethod
@@ -1,7 +1,7 @@
1
1
  from pixeltable.utils.code import local_public_names
2
2
 
3
- from . import (anthropic, audio, fireworks, huggingface, image, json, llama_cpp, mistralai, ollama, openai, string,
4
- timestamp, together, video, vision, whisper)
3
+ from . import (anthropic, audio, fireworks, gemini, huggingface, image, json, llama_cpp, mistralai, ollama, openai,
4
+ string, timestamp, together, video, vision, whisper)
5
5
  from .globals import *
6
6
 
7
7
  __all__ = local_public_names(__name__, exclude=['globals']) + local_public_names(globals.__name__)
@@ -0,0 +1,85 @@
1
+ """
2
+ Pixeltable [UDFs](https://pixeltable.readme.io/docs/user-defined-functions-udfs)
3
+ that wrap various endpoints from the Google Gemini API. In order to use them, you must
4
+ first `pip install google-generativeai` and configure your Gemini credentials, as described in
5
+ the [Working with Gemini](https://pixeltable.readme.io/docs/working-with-gemini) tutorial.
6
+ """
7
+
8
+ from typing import Optional
9
+
10
+ import pixeltable as pxt
11
+ from pixeltable import env
12
+
13
+
14
+ @env.register_client('gemini')
15
+ def _(api_key: str) -> None:
16
+ import google.generativeai as genai # type: ignore[import-untyped]
17
+ genai.configure(api_key=api_key)
18
+
19
+
20
+ def _ensure_loaded() -> None:
21
+ env.Env.get().get_client('gemini')
22
+
23
+
24
+ @pxt.udf
25
+ def generate_content(
26
+ contents: str,
27
+ *,
28
+ model_name: str,
29
+ candidate_count: Optional[int] = None,
30
+ stop_sequences: Optional[list[str]] = None,
31
+ max_output_tokens: Optional[int] = None,
32
+ temperature: Optional[float] = None,
33
+ top_p: Optional[float] = None,
34
+ top_k: Optional[int] = None,
35
+ response_mime_type: Optional[str] = None,
36
+ response_schema: Optional[dict] = None,
37
+ presence_penalty: Optional[float] = None,
38
+ frequency_penalty: Optional[float] = None,
39
+ response_logprobs: Optional[bool] = None,
40
+ logprobs: Optional[int] = None,
41
+ ) -> dict:
42
+ """
43
+ Generate content from the specified model. For additional details, see:
44
+ <https://ai.google.dev/gemini-api/docs>
45
+
46
+ __Requirements:__
47
+
48
+ - `pip install google-generativeai`
49
+
50
+ Args:
51
+ contents: The input content to generate from.
52
+ model_name: The name of the model to use.
53
+
54
+ For details on the other parameters, see: <https://ai.google.dev/gemini-api/docs>
55
+
56
+ Returns:
57
+ A dictionary containing the response and other metadata.
58
+
59
+ Examples:
60
+ Add a computed column that applies the model `gemini-1.5-flash`
61
+ to an existing Pixeltable column `tbl.prompt` of the table `tbl`:
62
+
63
+ >>> tbl['response'] = generate_content(tbl.prompt, model_name='gemini-1.5-flash')
64
+ """
65
+ env.Env.get().require_package('google.generativeai')
66
+ _ensure_loaded()
67
+ import google.generativeai as genai
68
+
69
+ model = genai.GenerativeModel(model_name=model_name)
70
+ gc = genai.GenerationConfig(
71
+ candidate_count=candidate_count,
72
+ stop_sequences=stop_sequences,
73
+ max_output_tokens=max_output_tokens,
74
+ temperature=temperature,
75
+ top_p=top_p,
76
+ top_k=top_k,
77
+ response_mime_type=response_mime_type,
78
+ response_schema=response_schema,
79
+ presence_penalty=presence_penalty,
80
+ frequency_penalty=frequency_penalty,
81
+ response_logprobs=response_logprobs,
82
+ logprobs=logprobs,
83
+ )
84
+ response = model.generate_content(contents, generation_config=gc)
85
+ return response.to_dict()
@@ -132,7 +132,7 @@ def _get_metadata(path: str) -> dict:
132
132
  assert isinstance(container, av.container.InputContainer)
133
133
  streams_info = [__get_stream_metadata(stream) for stream in container.streams]
134
134
  result = {
135
- 'bit_exact': container.bit_exact,
135
+ 'bit_exact': getattr(container, 'bit_exact', False),
136
136
  'bit_rate': container.bit_rate,
137
137
  'size': container.size,
138
138
  'metadata': container.metadata,
@@ -151,6 +151,9 @@ class DocumentSplitter(ComponentIterator):
151
151
  elif self._doc_handle.format == DocumentType.DocumentFormat.PDF:
152
152
  assert self._doc_handle.pdf_doc is not None
153
153
  self._sections = self._pdf_sections()
154
+ elif self._doc_handle.format == DocumentType.DocumentFormat.TXT:
155
+ assert self._doc_handle.txt_doc is not None
156
+ self._sections = self._txt_sections()
154
157
  else:
155
158
  assert False, f'Unsupported document format: {self._doc_handle.format}'
156
159
 
@@ -389,6 +392,15 @@ class DocumentSplitter(ComponentIterator):
389
392
  if accumulated_text and not emit_on_page:
390
393
  yield DocumentSection(text=_emit_text(), metadata=DocumentSectionMetadata())
391
394
 
395
+ def _txt_sections(self) -> Iterator[DocumentSection]:
396
+ """Create DocumentSections for text files.
397
+
398
+ Currently, it returns the entire text as a single section.
399
+ TODO: Add support for paragraphs.
400
+ """
401
+ assert self._doc_handle.txt_doc is not None
402
+ yield DocumentSection(text=ftfy.fix_text(self._doc_handle.txt_doc), metadata=DocumentSectionMetadata())
403
+
392
404
  def _sentence_sections(self, input_sections: Iterable[DocumentSection]) -> Iterator[DocumentSection]:
393
405
  """Split the input sections into sentences"""
394
406
  for section in input_sections:
pixeltable/type_system.py CHANGED
@@ -902,7 +902,7 @@ class VideoType(ColumnType):
902
902
  if num_decoded < 2:
903
903
  # this is most likely an image file
904
904
  raise excs.Error(f'Not a valid video: {val}')
905
- except av.AVError:
905
+ except av.FFmpegError:
906
906
  raise excs.Error(f'Not a valid video: {val}') from None
907
907
 
908
908
 
@@ -929,7 +929,7 @@ class AudioType(ColumnType):
929
929
  for packet in container.demux(audio_stream):
930
930
  for _ in packet.decode():
931
931
  pass
932
- except av.AVError as e:
932
+ except av.FFmpegError as e:
933
933
  raise excs.Error(f'Not a valid audio file: {val}\n{e}') from None
934
934
 
935
935
 
@@ -940,6 +940,7 @@ class DocumentType(ColumnType):
940
940
  MD = 1
941
941
  PDF = 2
942
942
  XML = 3
943
+ TXT = 4
943
944
 
944
945
  def __init__(self, nullable: bool = False, doc_formats: Optional[str] = None):
945
946
  super().__init__(self.Type.DOCUMENT, nullable=nullable)
@@ -15,6 +15,7 @@ class DocumentHandle:
15
15
  bs_doc: Optional[bs4.BeautifulSoup] = None
16
16
  md_ast: Optional[dict] = None
17
17
  pdf_doc: Optional[fitz.Document] = None
18
+ txt_doc: Optional[str] = None
18
19
 
19
20
 
20
21
  def get_document_handle(path: str) -> Optional[DocumentHandle]:
@@ -40,6 +41,11 @@ def get_document_handle(path: str) -> Optional[DocumentHandle]:
40
41
  if bs_doc is not None:
41
42
  return DocumentHandle(format=ts.DocumentType.DocumentFormat.XML, bs_doc=bs_doc)
42
43
 
44
+ if doc_format == '.txt':
45
+ txt_doc = get_txt(path)
46
+ if txt_doc is not None:
47
+ return DocumentHandle(format=ts.DocumentType.DocumentFormat.TXT, txt_doc=txt_doc)
48
+
43
49
  return None
44
50
 
45
51
 
@@ -84,3 +90,11 @@ def get_markdown_handle(path: str) -> Optional[dict]:
84
90
  return md_ast(text)
85
91
  except Exception:
86
92
  return None
93
+
94
+ def get_txt(path: str) -> Optional[str]:
95
+ try:
96
+ with open(path, "r") as f:
97
+ doc = f.read()
98
+ return doc if doc != '' else None
99
+ except Exception:
100
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pixeltable
3
- Version: 0.2.26
3
+ Version: 0.2.28
4
4
  Summary: AI Data Infrastructure: Declarative, Multimodal, and Incremental
5
5
  Home-page: https://pixeltable.com/
6
6
  License: Apache-2.0
@@ -1,5 +1,5 @@
1
1
  pixeltable/__init__.py,sha256=gv2jvZ7H5tEjLear10E7hSH9jF5Mw6iSeryvRp88bOE,1391
2
- pixeltable/__version__.py,sha256=5OkFhhUIXyKPz2LjEv1DUzoaDvZXzsOKyF_UesfvD_U,114
2
+ pixeltable/__version__.py,sha256=l8o30KW84uYtvfwZm9WIrXqImTKS_XYYoG3YZr7yaaQ,114
3
3
  pixeltable/catalog/__init__.py,sha256=Ar6_F_6C7tkznIlCPBHVHDop5YssBDjKQr2NPQ21QCI,484
4
4
  pixeltable/catalog/catalog.py,sha256=tyDyI5wQw7vV6_FChrp9qgGCRClcjiSdW3eygYT0p9s,7849
5
5
  pixeltable/catalog/column.py,sha256=ezeKoGl6aBTzSZBihDA6vdETcvyCguAD4OsmrxWs73A,9595
@@ -15,7 +15,7 @@ pixeltable/catalog/table_version.py,sha256=W4yrvn-mF63CQ8cQGmjbjYTCf1xYuV6k6rI__
15
15
  pixeltable/catalog/table_version_path.py,sha256=CczGbcz5ESq663arreri_p4chMZHozgG6k3y-ajkJN4,5787
16
16
  pixeltable/catalog/view.py,sha256=mJbaVE63GaBDy7EcQkQ2q5NKlrHlGyENkRyQVzU-ak8,10854
17
17
  pixeltable/dataframe.py,sha256=RnRpOWLOqKNHGK2cO-Zbbc63yLUqrX7eSCYW11K4n7A,41320
18
- pixeltable/env.py,sha256=oIFeLJVDQuQgW8REAoNkY45BF2o02NxtysgAlJNEBc8,30520
18
+ pixeltable/env.py,sha256=zmEdcMj_nKIsPJ-sKB1Avi3AnacGQOuk-uP1tQhh1tU,30840
19
19
  pixeltable/exceptions.py,sha256=NuFY2WtkQpLfLHT_J70kOw9Tr0kEDkkgo-u7As4Gaq4,410
20
20
  pixeltable/exec/__init__.py,sha256=bWbIA7U7y1hC40VOSv_p9doaMuOB0i3r1O2UFNw0VEs,494
21
21
  pixeltable/exec/aggregation_node.py,sha256=0LdoPp_CR_UbcS60XkDw66SqlrQnw6Dy6KDWqi4PJ6k,4005
@@ -36,7 +36,7 @@ pixeltable/exprs/column_ref.py,sha256=Z2YAiZ0nMv_ecbw91qTc9VN6DB2hZj-_RNkogZcu4n
36
36
  pixeltable/exprs/comparison.py,sha256=w1FuhnGsJRoCLYX3ztIHZDywf8nZeT2tKKwRjIQa6Lc,5101
37
37
  pixeltable/exprs/compound_predicate.py,sha256=6N_zN4A_hKGLordNY0si-8KHeFWG1UtyeiTHcs69IrM,3846
38
38
  pixeltable/exprs/data_row.py,sha256=rLtKxlst9mK6684A5y-nsjBcalyKEcKAWcYCtNpK10w,9852
39
- pixeltable/exprs/expr.py,sha256=uEyM9cMCkUM0PXIhWh0KhLYkRnEf2ysE3rQQTeDbHP0,30427
39
+ pixeltable/exprs/expr.py,sha256=E1V_fU1qA4nkHLHTqGkxr8exJE6I9-b9LwNVXxGNTXo,30463
40
40
  pixeltable/exprs/expr_dict.py,sha256=xkvo_iVPOLMq3WkBZQ2FOoXqYoebuV6XGlidPJxdOkY,1588
41
41
  pixeltable/exprs/expr_set.py,sha256=GeUQXadzJbAqQOGdsO6Z5hPAp0A03YUr2hyIvfZDYEE,2576
42
42
  pixeltable/exprs/function_call.py,sha256=YojOWiveyZ3kS8zDQs1uwu95w5--Su5TK1vCFZL_PpQ,21416
@@ -69,10 +69,11 @@ pixeltable/func/globals.py,sha256=sEwn6lGgHMp6VQORb_P5qRd_-Q2_bUSqvqM9-XPN_ec,14
69
69
  pixeltable/func/query_template_function.py,sha256=pGqwtWiPsEmo7phVoJJODiuD1Sh0gZoW4BpKnZV9cRE,3537
70
70
  pixeltable/func/signature.py,sha256=MzOHayuf2S3EWIl4IRtdNWnaKj5tphnw1z7P6xNU6Xg,8691
71
71
  pixeltable/func/udf.py,sha256=_883xbGujeIhYOz-lWH5SvLn22F5JVpP6O_MRvpU4hU,7362
72
- pixeltable/functions/__init__.py,sha256=EtR9M3ewYpmtHeshNULqZVBd87bNeKSFAdpOuWCMl6o,389
72
+ pixeltable/functions/__init__.py,sha256=2lsAds20ZUEJETkGmGXjWSqzmGhPABcuGWOe1IZjqxs,397
73
73
  pixeltable/functions/anthropic.py,sha256=P1E5o4-8QP1LTIUsWVgo_wMJ4WOnxtXUUXuFWUagChU,3032
74
74
  pixeltable/functions/audio.py,sha256=7213nTnqKJ6vM9kalaoJ283OwX5SGEJN10vDhaRNZ6E,644
75
75
  pixeltable/functions/fireworks.py,sha256=qwFC_eIaDs-glxyJ_IVXaNGkpgPzeRsQ_SdpzueBxq0,2605
76
+ pixeltable/functions/gemini.py,sha256=RQ3I25nXSXUXdF0rmhnv5XOgZXb_6SIgMc_hEyF83SI,2783
76
77
  pixeltable/functions/globals.py,sha256=pCFX2a_N87SwG9GxyPjSOC3TVMowMB6XIHSWKfFOuGE,3917
77
78
  pixeltable/functions/huggingface.py,sha256=s5KmOfi9-TOYyrL1Wv-voKP7ykkUN7LlLAA_uo01UQc,21210
78
79
  pixeltable/functions/image.py,sha256=3Qm4ybAT_o4YUl3bzhEXy8dKOwgZ7RCUV-ky-dbL_jc,13836
@@ -86,7 +87,7 @@ pixeltable/functions/string.py,sha256=VqzhVildxTt_XblW89Kl5Zd6MVOU71eaX2LTMY5jkU
86
87
  pixeltable/functions/timestamp.py,sha256=Q5l2iEscrS3ZfKAa4R940bSM_x4FsmF-PF2i-wQ_4_c,9096
87
88
  pixeltable/functions/together.py,sha256=xbgQMlA2G2FXdoQR4O9DlkmBsm2mivAdiOnxtxcyPwo,9440
88
89
  pixeltable/functions/util.py,sha256=GgKTzCjvzUQNjWtSObTkfxkvJ9GVUOzKimY45WhE25M,759
89
- pixeltable/functions/video.py,sha256=yW1Lwqu4_jYXp1aAOUThKB5-_Qxy-In_vTgB5cuW7Lg,6809
90
+ pixeltable/functions/video.py,sha256=WpJc84xoQ6PQqp0EzBgBLhRgi6H8GY2t9C-FvpZ4Ivo,6828
90
91
  pixeltable/functions/vision.py,sha256=K_E1Q-n2plPuFoOPlbKWRMiJp9dPgftIJ2T_o3TNL3I,15594
91
92
  pixeltable/functions/whisper.py,sha256=f2wqRd0n9jSBqRZN3W93UaetiAHtbsK0j9jXR2j2kkQ,2913
92
93
  pixeltable/globals.py,sha256=Ahfq5Au0HvL9W9oBOnf3-EzAOEAfagtiVxEgh3IznJg,20522
@@ -104,7 +105,7 @@ pixeltable/io/pandas.py,sha256=7eHg7wnAfRA9eBk4iC0iSSVTKOM59Ne4pXokKWdt3dY,9793
104
105
  pixeltable/io/parquet.py,sha256=bvwTRIKhS99M3bAcAP63jnh5-R6Qww1SrYBGWjZvN1g,8800
105
106
  pixeltable/iterators/__init__.py,sha256=qA9cJTwPO3gk-7y8mUXw2anWSbnUAVGwzl52SxiUjNU,398
106
107
  pixeltable/iterators/base.py,sha256=ZC0ZvXL4iw6AmT8cu-Mdx-T2UG9nmJYV1C6LK4efAfw,1669
107
- pixeltable/iterators/document.py,sha256=AsvEmZ5RGRi3AFGCrH2_-UNx5rTCFA-0WmMYQBTQI20,19679
108
+ pixeltable/iterators/document.py,sha256=e5EMUAW4f5SqfC5mRN7Oo2E3gw_vcMSzq2707NVLByU,20254
108
109
  pixeltable/iterators/image.py,sha256=7eJupbyLEl_q4bemEozL8WgTgkxjl-DYnSXyHTQ7Rck,3628
109
110
  pixeltable/iterators/string.py,sha256=NG_fWc_GAITDfzl6MvrDOMrSoMcZdMZf6hPQztCSatE,1305
110
111
  pixeltable/iterators/video.py,sha256=anedQpSOnjYhHLa8UiEx-6ROagb14rpXh9am8oTriUg,9382
@@ -134,13 +135,13 @@ pixeltable/tool/doc_plugins/mkdocstrings.py,sha256=afq7XOaSC5WRmugkh-FMFMK8PqOgI
134
135
  pixeltable/tool/doc_plugins/templates/material/udf.html.jinja,sha256=R-7Q57nmDd5BUea-F1-MjwjK3pq7uBHXNoSo8_QjZG4,4890
135
136
  pixeltable/tool/embed_udf.py,sha256=EXvfvuzZm0uTgH-aAATSrKV8ixCU8OMwpzXlJMg845Y,299
136
137
  pixeltable/tool/mypy_plugin.py,sha256=__oTFElirrK25jCX1z_asD_gxGnGxtD2TaU6r1if-Ic,1784
137
- pixeltable/type_system.py,sha256=QPQ2Q065WQJY7uz1U3Y5dlgUPYwnWxBYfPmiZZXb-JE,41936
138
+ pixeltable/type_system.py,sha256=80Q70uiOKOm3EOv2Gj0PFgwLUdMq7unMEEok58xvtgQ,41960
138
139
  pixeltable/utils/__init__.py,sha256=UYlrf6TIWJT0g-Hac0b34-dEk478B5Qx8dGco34YlIk,439
139
140
  pixeltable/utils/arrow.py,sha256=4AyCAkkNfNChVTaPAVS5j1ZO7BtTxn11duonolfktV8,3931
140
141
  pixeltable/utils/coco.py,sha256=WCUyoj0dTyJFbPB7frEQUvY92SlEPxQ068r-3QAwROE,7285
141
142
  pixeltable/utils/code.py,sha256=AOw1u2r8_DQXpX-lxJhyHWARGrCRDXOJHFVgKOi54Uc,1231
142
143
  pixeltable/utils/description_helper.py,sha256=P-8EE2pRFP8s3coe73frgV68yt4Dp3saErCUehMxKUw,3759
143
- pixeltable/utils/documents.py,sha256=B984nVigJgHZ5Rm-zX4LLuHuMnfmz-zr24bbAsc_y3w,2511
144
+ pixeltable/utils/documents.py,sha256=pytTYY167wYc1rGaDd9HPK6GOrz1ML78eAD3hIHrG68,2930
144
145
  pixeltable/utils/filecache.py,sha256=6HKQdItqSSTQvj2HkSJulyhfBedi4PgC7umwxXGOVG8,10637
145
146
  pixeltable/utils/formatter.py,sha256=5E_gDg11ClFI-5SthwkiqyE3hAok3JHDj4OSK9cJklM,9257
146
147
  pixeltable/utils/http_server.py,sha256=xYPTvmYrkUpKfOaLDq08D-eHswkcgDf4qAt76ZFH6lM,2411
@@ -149,8 +150,8 @@ pixeltable/utils/pytorch.py,sha256=6RvOCjy_QV4gc-aht-3d0zoASkuv-warfpl87vgmuKw,3
149
150
  pixeltable/utils/s3.py,sha256=huA5hxDGkPIu18zWet76o0FsO7Vbtp-iPmnOzCe-MvA,586
150
151
  pixeltable/utils/sql.py,sha256=j_tj0h4ffm-DhUIJbvGphxrVyBKlNTwDKqWGhRQ5_PY,795
151
152
  pixeltable/utils/transactional_directory.py,sha256=UGzCrGtLR3hEEf8sYGuWBzLVFAEQml3vdIavigWeTBM,1349
152
- pixeltable-0.2.26.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
153
- pixeltable-0.2.26.dist-info/METADATA,sha256=qgtP333OuS_5GC1MBPPuS7Eu3V_Kb1hXxcnEs3l0QLA,19476
154
- pixeltable-0.2.26.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
155
- pixeltable-0.2.26.dist-info/entry_points.txt,sha256=TNI1Gb5vPwFrTdw6TimSYjO8FeK8c_HuPr28vcf7o_I,108
156
- pixeltable-0.2.26.dist-info/RECORD,,
153
+ pixeltable-0.2.28.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
154
+ pixeltable-0.2.28.dist-info/METADATA,sha256=Ven2L4mYf11p8j361tzOMwVWjt-Pjom5vdJLw1ggFX0,19476
155
+ pixeltable-0.2.28.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
156
+ pixeltable-0.2.28.dist-info/entry_points.txt,sha256=TNI1Gb5vPwFrTdw6TimSYjO8FeK8c_HuPr28vcf7o_I,108
157
+ pixeltable-0.2.28.dist-info/RECORD,,