clams-python 1.7.3__tar.gz → 1.7.4__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.
- {clams_python-1.7.3 → clams_python-1.7.4}/CHANGELOG.md +9 -0
- {clams_python-1.7.3/clams_python.egg-info → clams_python-1.7.4}/PKG-INFO +1 -1
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/app/__init__.py +77 -18
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/Containerfile.template +1 -1
- {clams_python-1.7.3 → clams_python-1.7.4/clams_python.egg-info}/PKG-INFO +1 -1
- {clams_python-1.7.3 → clams_python-1.7.4}/clams_python.egg-info/scm_file_list.json +67 -67
- clams_python-1.7.4/clams_python.egg-info/scm_version.json +8 -0
- clams_python-1.7.4/container/ffmpeg-torch2.containerfile +13 -0
- clams_python-1.7.4/container/opencv4-torch2.containerfile +13 -0
- clams_python-1.7.4/container/torch2.containerfile +13 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/app-baseclasses.rst +5 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/clamsapp.rst +12 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/introduction.rst +1 -1
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/runtime-params.rst +9 -1
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/target-versions.csv +1 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/tests/test_clamsapp.py +77 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/tests/test_envelope.py +13 -0
- clams_python-1.7.3/clams_python.egg-info/scm_version.json +0 -8
- clams_python-1.7.3/container/ffmpeg-torch2.containerfile +0 -6
- clams_python-1.7.3/container/opencv4-torch2.containerfile +0 -6
- clams_python-1.7.3/container/torch2.containerfile +0 -6
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/codecov.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/container.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/containers.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/issue-assign.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/issue-close.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/issue-infra-project.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/publish.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.github/workflows/release-check.yml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.gitignore +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/.pytype.cfg +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/CONTRIBUTING.md +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/LICENSE +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/README.md +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/build-tools/build.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/build-tools/clean.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/build-tools/docs.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/build-tools/prep_release.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/build-tools/publish.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/build-tools/test.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/appmetadata/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/backends/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/backends/hf.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/.dockerignore.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/.gitignore.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/LICENSE.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/README.md.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/app.py.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/cli.py.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/metadata.py.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/requirements.txt.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/gha/for-clams-team.md.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/gha/workflows/issue-apps-project.yml.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/gha/workflows/issue-assign.yml.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/gha/workflows/issue-close.yml.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/gha/workflows/publish.yml.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/utl-tf/__init__.py.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/utl-tf/timeframe.py.template +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/envelop/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/restify/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/serve/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams/ver/__init__.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams_python.egg-info/SOURCES.txt +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams_python.egg-info/dependency_links.txt +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams_python.egg-info/entry_points.txt +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams_python.egg-info/requires.txt +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/clams_python.egg-info/top_level.txt +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/Containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/ffmpeg-hf.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/ffmpeg-hf4.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/ffmpeg-hf5.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/ffmpeg-tf2.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/ffmpeg.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/generate_containers_yml.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/hf.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/hf4.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/hf5.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/jdk8.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/opencv4-hf.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/opencv4-hf4.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/opencv4-hf5.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/opencv4-tf2.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/opencv4.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/container/tf2.containerfile +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/appdirectory.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/appmetadata.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/autodoc/clams.app.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/autodoc/clams.appmetadata.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/autodoc/clams.backends.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/autodoc/clams.mmif_utils.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/autodoc/clams.restify.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/cli.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/conf.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/gpu-apps.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/index.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/input-output.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/modules.rst +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/documentation/tutorial.md +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/pyproject.toml +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/setup.cfg +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/tests/metadata.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/tests/pillow-logo.png +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/tests/test_backends_hf.py +0 -0
- {clams_python-1.7.3 → clams_python-1.7.4}/tests/test_promptable.py +0 -0
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
|
|
2
|
+
## releasing 1.7.3 (2026-07-09)
|
|
3
|
+
### Overview
|
|
4
|
+
This patch includes critical bugfixes. See changes below.
|
|
5
|
+
|
|
6
|
+
### Changes
|
|
7
|
+
* fixes handling of error during `annotate()` (and `_annotate()`) when running an app via cli.py (#297)
|
|
8
|
+
* added the `useReasoning` common parameter for promptable apps (#299) Note that release 1.7.2 was supposed to include this parameter (and the release note says so), but it was omitted by mistake.
|
|
9
|
+
|
|
10
|
+
|
|
2
11
|
## releasing 1.7.2 (2026-07-07)
|
|
3
12
|
### Overview
|
|
4
13
|
This patch adds experimental handling of "reasoning traces" of propmtable apps
|
|
@@ -49,6 +49,10 @@ falsy_values = [
|
|
|
49
49
|
]
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
class EmptyOutputWarning(UserWarning):
|
|
53
|
+
"""Raised when an app's ``_annotate()`` produces no non-empty views."""
|
|
54
|
+
|
|
55
|
+
|
|
52
56
|
class ClamsApp(ABC):
|
|
53
57
|
"""
|
|
54
58
|
An abstract class to define API's for ClamsApps. A CLAMS app should inherit
|
|
@@ -191,6 +195,15 @@ class ClamsApp(ABC):
|
|
|
191
195
|
t = datetime.now()
|
|
192
196
|
with warnings.catch_warnings(record=True) as ws:
|
|
193
197
|
annotated, cuda_profiler = self._profile_cuda_memory(self._annotate)(mmif, **refined)
|
|
198
|
+
new_views = [v for v in annotated.views if v.id not in existing_view_ids]
|
|
199
|
+
is_empty = lambda v: len(v.annotations) == 0 and not v.has_error() and not v.has_warnings()
|
|
200
|
+
for v in new_views:
|
|
201
|
+
if is_empty(v):
|
|
202
|
+
del annotated.views._items[v.id] # no public API to remove a view (mmif-python)
|
|
203
|
+
if all(is_empty(v) for v in new_views):
|
|
204
|
+
warnings.warn(f'App "{self.metadata.identifier}" produced no annotations for this '
|
|
205
|
+
f'input; the input may lack expected content, or there may genuinely '
|
|
206
|
+
f'be nothing to annotate.', EmptyOutputWarning)
|
|
194
207
|
if ws:
|
|
195
208
|
issued_warnings.extend(ws)
|
|
196
209
|
if issued_warnings:
|
|
@@ -301,35 +314,81 @@ class ClamsApp(ABC):
|
|
|
301
314
|
"""
|
|
302
315
|
A method to "sign" a new view that this app creates at the beginning of annotation.
|
|
303
316
|
Signing will populate the view metadata with information and configuration of this app.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
317
|
+
|
|
318
|
+
The ``runtime_conf`` argument can be either "refined" or "raw" parameters,
|
|
319
|
+
and what ends up recorded in the view metadata differs accordingly:
|
|
320
|
+
|
|
321
|
+
* "refined" params: the output of :meth:`~clams.app.ClamsApp._refine_params`,
|
|
322
|
+
identifiable by the presence of the internal ``_RAW_PARAMS_KEY`` marker.
|
|
323
|
+
These carry both the user's raw input and the fully resolved configuration
|
|
324
|
+
(declared parameters with their defaults filled in). Signing then populates
|
|
325
|
+
**two** metadata fields: ``parameters`` with the raw user input (before
|
|
326
|
+
defaults), and ``appConfiguration`` with the resolved configuration,
|
|
327
|
+
including the universal parameters (e.g. ``pretty``, ``runningTime``,
|
|
328
|
+
``hwFetch``, ``tfSamplingMode``).
|
|
329
|
+
* "raw" params: an unrefined ``Dict[str, List[str]]``. Only the
|
|
330
|
+
``parameters`` field is populated; there is no resolved configuration
|
|
331
|
+
to record. See :meth:`~clams.app.ClamsApp.add_parameters_to_metadata`
|
|
332
|
+
for the input channels these values come from and how each is recorded.
|
|
333
|
+
|
|
334
|
+
These two cases exist because of two distinct execution paths. On the normal
|
|
335
|
+
annotation path, :meth:`~clams.app.ClamsApp.annotate` refines the parameters
|
|
336
|
+
before invoking :meth:`~clams.app.ClamsApp._annotate`, so a well-behaved app
|
|
337
|
+
forwards those already-refined params here and gets the full two-field record.
|
|
338
|
+
On the error path (:meth:`~clams.app.ClamsApp.set_error_view`), refinement may
|
|
339
|
+
be exactly what failed (:meth:`~clams.app.ClamsApp._refine_params` raises on a
|
|
340
|
+
missing required parameter or an invalid choice) so the error view is signed
|
|
341
|
+
with the raw params to guarantee the error is still recorded.
|
|
342
|
+
|
|
308
343
|
:param view: a view to sign
|
|
309
|
-
:param runtime_conf: runtime configuration of the app
|
|
344
|
+
:param runtime_conf: runtime configuration of the app, either refined
|
|
345
|
+
(output of :meth:`~clams.app.ClamsApp._refine_params`) or raw k-v pairs
|
|
310
346
|
"""
|
|
311
347
|
view.metadata.app = str(self.metadata.identifier)
|
|
312
348
|
if self.metadata.app_tags:
|
|
313
349
|
view.metadata.set_additional_property('appTags', list(self.metadata.app_tags))
|
|
314
|
-
params_map = {p.name: p for p in self.metadata.parameters}
|
|
315
350
|
if self._RAW_PARAMS_KEY in runtime_conf:
|
|
316
351
|
for k, v in runtime_conf.items():
|
|
317
352
|
if k == self._RAW_PARAMS_KEY:
|
|
318
|
-
|
|
319
|
-
if orik in params_map and params_map[orik].multivalued:
|
|
320
|
-
view.metadata.add_parameter(orik, str(oriv))
|
|
321
|
-
else:
|
|
322
|
-
view.metadata.add_parameter(orik, oriv[0])
|
|
353
|
+
self.add_parameters_to_metadata(view, v)
|
|
323
354
|
else:
|
|
324
355
|
view.metadata.add_app_configuration(k, v)
|
|
325
356
|
else:
|
|
326
|
-
#
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
357
|
+
# unrefined params passed directly (no _RAW_PARAMS_KEY marker), e.g.
|
|
358
|
+
# the error path; values are lists
|
|
359
|
+
self.add_parameters_to_metadata(view, runtime_conf)
|
|
360
|
+
|
|
361
|
+
def add_parameters_to_metadata(self, view: View, parameters: dict):
|
|
362
|
+
"""
|
|
363
|
+
Record raw runtime parameters into the view's ``parameters`` metadata.
|
|
364
|
+
|
|
365
|
+
The ``parameters`` argument reaches an app through one of three channels:
|
|
366
|
+
|
|
367
|
+
#. a query string, when the app runs as an HTTP server (``app.py``, via
|
|
368
|
+
:class:`~clams.restify.Restifier`);
|
|
369
|
+
#. shell arguments, when the app runs as a CLI program (``cli.py``);
|
|
370
|
+
#. a JSON envelope built with the ``clams envelop`` command (see
|
|
371
|
+
:mod:`clams.envelop`), whose values are flattened by
|
|
372
|
+
:func:`~clams.envelop.normalize_params`.
|
|
373
|
+
|
|
374
|
+
In every case the values arrive as ``List[str]`` (the shape
|
|
375
|
+
:meth:`~clams.app.ClamsApp._refine_params` consumes). A single value is
|
|
376
|
+
recorded bare with the ``List`` wrapper stripped, multiple values as the
|
|
377
|
+
serialized list, and an empty list skipped as unset (only an envelope
|
|
378
|
+
such as ``{"x": []}`` produces one, guarding against an ``IndexError``
|
|
379
|
+
on ``v[0]``).
|
|
380
|
+
|
|
381
|
+
:param view: the view being signed
|
|
382
|
+
:param parameters: raw runtime parameters as ``Dict[str, List[str]]``
|
|
383
|
+
"""
|
|
384
|
+
for k, v in parameters.items():
|
|
385
|
+
if len(v) == 0:
|
|
386
|
+
continue
|
|
387
|
+
elif len(v) == 1:
|
|
388
|
+
view.metadata.add_parameter(k, v[0])
|
|
389
|
+
else:
|
|
390
|
+
view.metadata.add_parameter(k, str(v))
|
|
391
|
+
|
|
333
392
|
def set_error_view(self, mmif: Union[str, dict, Mmif], **runtime_conf: List[str]) -> Mmif:
|
|
334
393
|
"""
|
|
335
394
|
A method to record an error instead of annotation results in the view
|
{clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/Containerfile.template
RENAMED
|
@@ -3,7 +3,7 @@ FROM ghcr.io/clamsproject/clams-python:$CLAMS_VERSION
|
|
|
3
3
|
# See https://github.com/orgs/clamsproject/packages?tab=packages&q=clams-python for more base images
|
|
4
4
|
# IF you want to automatically publish this image to the clamsproject organization,
|
|
5
5
|
# 1. you should have generated this template without --no-github-actions flag
|
|
6
|
-
# 1. to add arm64 support,
|
|
6
|
+
# 1. to add arm64 support, set `arm64: true` in .github/workflows/publish.yml
|
|
7
7
|
# * NOTE that a lots of software doesn't install/compile or run on arm64 architecture out of the box
|
|
8
8
|
# * make sure you locally test the compatibility of all software dependencies before using arm64 support
|
|
9
9
|
# 1. use a git tag to trigger the github action. You need to use git tag to properly set app version anyway
|
|
@@ -1,96 +1,96 @@
|
|
|
1
1
|
{
|
|
2
2
|
"files": [
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
".github/workflows/codecov.yml",
|
|
4
|
+
".github/workflows/container.yml",
|
|
5
|
+
".github/workflows/containers.yml",
|
|
6
|
+
".github/workflows/issue-assign.yml",
|
|
7
|
+
".github/workflows/issue-close.yml",
|
|
8
|
+
".github/workflows/issue-infra-project.yml",
|
|
9
|
+
".github/workflows/publish.yml",
|
|
10
|
+
".github/workflows/release-check.yml",
|
|
11
|
+
".gitignore",
|
|
6
12
|
".pytype.cfg",
|
|
7
13
|
"CHANGELOG.md",
|
|
8
14
|
"CONTRIBUTING.md",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"build-tools/prep_release.py",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"README.md",
|
|
12
17
|
"build-tools/build.py",
|
|
13
|
-
"build-tools/docs.py",
|
|
14
18
|
"build-tools/clean.py",
|
|
19
|
+
"build-tools/docs.py",
|
|
20
|
+
"build-tools/prep_release.py",
|
|
21
|
+
"build-tools/publish.py",
|
|
15
22
|
"build-tools/test.py",
|
|
16
23
|
"clams/__init__.py",
|
|
24
|
+
"clams/app/__init__.py",
|
|
25
|
+
"clams/appmetadata/__init__.py",
|
|
26
|
+
"clams/backends/__init__.py",
|
|
27
|
+
"clams/backends/hf.py",
|
|
17
28
|
"clams/develop/__init__.py",
|
|
29
|
+
"clams/develop/templates/app/.dockerignore.template",
|
|
30
|
+
"clams/develop/templates/app/.gitignore.template",
|
|
31
|
+
"clams/develop/templates/app/Containerfile.template",
|
|
32
|
+
"clams/develop/templates/app/LICENSE.template",
|
|
33
|
+
"clams/develop/templates/app/README.md.template",
|
|
34
|
+
"clams/develop/templates/app/app.py.template",
|
|
35
|
+
"clams/develop/templates/app/cli.py.template",
|
|
36
|
+
"clams/develop/templates/app/metadata.py.template",
|
|
37
|
+
"clams/develop/templates/app/requirements.txt.template",
|
|
18
38
|
"clams/develop/templates/gha/for-clams-team.md.template",
|
|
19
|
-
"clams/develop/templates/gha/workflows/issue-assign.yml.template",
|
|
20
|
-
"clams/develop/templates/gha/workflows/publish.yml.template",
|
|
21
39
|
"clams/develop/templates/gha/workflows/issue-apps-project.yml.template",
|
|
40
|
+
"clams/develop/templates/gha/workflows/issue-assign.yml.template",
|
|
22
41
|
"clams/develop/templates/gha/workflows/issue-close.yml.template",
|
|
42
|
+
"clams/develop/templates/gha/workflows/publish.yml.template",
|
|
23
43
|
"clams/develop/templates/utl-tf/__init__.py.template",
|
|
24
44
|
"clams/develop/templates/utl-tf/timeframe.py.template",
|
|
25
|
-
"clams/develop/templates/app/Containerfile.template",
|
|
26
|
-
"clams/develop/templates/app/metadata.py.template",
|
|
27
|
-
"clams/develop/templates/app/README.md.template",
|
|
28
|
-
"clams/develop/templates/app/.dockerignore.template",
|
|
29
|
-
"clams/develop/templates/app/requirements.txt.template",
|
|
30
|
-
"clams/develop/templates/app/LICENSE.template",
|
|
31
|
-
"clams/develop/templates/app/.gitignore.template",
|
|
32
|
-
"clams/develop/templates/app/app.py.template",
|
|
33
|
-
"clams/develop/templates/app/cli.py.template",
|
|
34
|
-
"clams/restify/__init__.py",
|
|
35
45
|
"clams/envelop/__init__.py",
|
|
36
|
-
"clams/
|
|
37
|
-
"clams/app/__init__.py",
|
|
46
|
+
"clams/restify/__init__.py",
|
|
38
47
|
"clams/serve/__init__.py",
|
|
39
48
|
"clams/ver/__init__.py",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
49
|
+
"container/Containerfile",
|
|
50
|
+
"container/ffmpeg-hf.containerfile",
|
|
51
|
+
"container/ffmpeg-hf4.containerfile",
|
|
52
|
+
"container/ffmpeg-hf5.containerfile",
|
|
53
|
+
"container/ffmpeg-tf2.containerfile",
|
|
54
|
+
"container/ffmpeg-torch2.containerfile",
|
|
55
|
+
"container/ffmpeg.containerfile",
|
|
56
|
+
"container/generate_containers_yml.py",
|
|
57
|
+
"container/hf.containerfile",
|
|
58
|
+
"container/hf4.containerfile",
|
|
59
|
+
"container/hf5.containerfile",
|
|
60
|
+
"container/jdk8.containerfile",
|
|
61
|
+
"container/opencv4-hf.containerfile",
|
|
62
|
+
"container/opencv4-hf4.containerfile",
|
|
63
|
+
"container/opencv4-hf5.containerfile",
|
|
64
|
+
"container/opencv4-tf2.containerfile",
|
|
65
|
+
"container/opencv4-torch2.containerfile",
|
|
66
|
+
"container/opencv4.containerfile",
|
|
67
|
+
"container/tf2.containerfile",
|
|
68
|
+
"container/torch2.containerfile",
|
|
44
69
|
"documentation/app-baseclasses.rst",
|
|
45
|
-
"documentation/gpu-apps.rst",
|
|
46
|
-
"documentation/clamsapp.rst",
|
|
47
70
|
"documentation/appdirectory.rst",
|
|
48
|
-
"documentation/index.rst",
|
|
49
|
-
"documentation/tutorial.md",
|
|
50
|
-
"documentation/introduction.rst",
|
|
51
71
|
"documentation/appmetadata.rst",
|
|
52
|
-
"documentation/cli.rst",
|
|
53
|
-
"documentation/runtime-params.rst",
|
|
54
|
-
"documentation/input-output.rst",
|
|
55
|
-
"documentation/conf.py",
|
|
56
|
-
"documentation/autodoc/clams.restify.rst",
|
|
57
72
|
"documentation/autodoc/clams.app.rst",
|
|
73
|
+
"documentation/autodoc/clams.appmetadata.rst",
|
|
58
74
|
"documentation/autodoc/clams.backends.rst",
|
|
59
75
|
"documentation/autodoc/clams.mmif_utils.rst",
|
|
60
|
-
"documentation/autodoc/clams.
|
|
61
|
-
"
|
|
76
|
+
"documentation/autodoc/clams.restify.rst",
|
|
77
|
+
"documentation/clamsapp.rst",
|
|
78
|
+
"documentation/cli.rst",
|
|
79
|
+
"documentation/conf.py",
|
|
80
|
+
"documentation/gpu-apps.rst",
|
|
81
|
+
"documentation/index.rst",
|
|
82
|
+
"documentation/input-output.rst",
|
|
83
|
+
"documentation/introduction.rst",
|
|
84
|
+
"documentation/modules.rst",
|
|
85
|
+
"documentation/runtime-params.rst",
|
|
86
|
+
"documentation/target-versions.csv",
|
|
87
|
+
"documentation/tutorial.md",
|
|
88
|
+
"pyproject.toml",
|
|
89
|
+
"tests/metadata.py",
|
|
62
90
|
"tests/pillow-logo.png",
|
|
63
91
|
"tests/test_backends_hf.py",
|
|
64
|
-
"tests/test_envelope.py",
|
|
65
|
-
"tests/metadata.py",
|
|
66
92
|
"tests/test_clamsapp.py",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"container/torch2.containerfile",
|
|
70
|
-
"container/opencv4-hf4.containerfile",
|
|
71
|
-
"container/Containerfile",
|
|
72
|
-
"container/hf4.containerfile",
|
|
73
|
-
"container/ffmpeg-hf.containerfile",
|
|
74
|
-
"container/ffmpeg-tf2.containerfile",
|
|
75
|
-
"container/generate_containers_yml.py",
|
|
76
|
-
"container/opencv4-tf2.containerfile",
|
|
77
|
-
"container/opencv4-torch2.containerfile",
|
|
78
|
-
"container/hf.containerfile",
|
|
79
|
-
"container/jdk8.containerfile",
|
|
80
|
-
"container/hf5.containerfile",
|
|
81
|
-
"container/ffmpeg.containerfile",
|
|
82
|
-
"container/ffmpeg-hf5.containerfile",
|
|
83
|
-
"container/ffmpeg-hf4.containerfile",
|
|
84
|
-
"container/opencv4-hf5.containerfile",
|
|
85
|
-
"container/ffmpeg-torch2.containerfile",
|
|
86
|
-
"container/opencv4.containerfile",
|
|
87
|
-
".github/workflows/container.yml",
|
|
88
|
-
".github/workflows/containers.yml",
|
|
89
|
-
".github/workflows/issue-close.yml",
|
|
90
|
-
".github/workflows/codecov.yml",
|
|
91
|
-
".github/workflows/release-check.yml",
|
|
92
|
-
".github/workflows/issue-infra-project.yml",
|
|
93
|
-
".github/workflows/issue-assign.yml",
|
|
94
|
-
".github/workflows/publish.yml"
|
|
93
|
+
"tests/test_envelope.py",
|
|
94
|
+
"tests/test_promptable.py"
|
|
95
95
|
]
|
|
96
96
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ARG clams_version
|
|
2
|
+
FROM ghcr.io/clamsproject/clams-python-ffmpeg:$clams_version
|
|
3
|
+
LABEL org.opencontainers.image.description="clams-python-ffmpeg-torch2 image is shipped with clams-python, ffmpeg, and PyTorch2"
|
|
4
|
+
|
|
5
|
+
RUN pip install --no-cache-dir torch==2.*
|
|
6
|
+
|
|
7
|
+
# PyTorch ships Triton, which JIT-compiles a small host-side CUDA driver shim
|
|
8
|
+
# at runtime -- that needs a C compiler + libc headers. Keep it minimal
|
|
9
|
+
# (gcc + libc6-dev); build-essential is not required.
|
|
10
|
+
RUN apt-get update \
|
|
11
|
+
&& apt-get install -y --no-install-recommends gcc libc6-dev \
|
|
12
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
13
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ARG clams_version
|
|
2
|
+
FROM ghcr.io/clamsproject/clams-python-opencv4:$clams_version
|
|
3
|
+
LABEL org.opencontainers.image.description="clams-python-opencv4-torch2 image is shipped with clams-python, opencv4 (ffmpeg backend), and PyTorch2"
|
|
4
|
+
|
|
5
|
+
RUN pip install --no-cache-dir torch==2.*
|
|
6
|
+
|
|
7
|
+
# PyTorch ships Triton, which JIT-compiles a small host-side CUDA driver shim
|
|
8
|
+
# at runtime -- that needs a C compiler + libc headers. Keep it minimal
|
|
9
|
+
# (gcc + libc6-dev); build-essential is not required.
|
|
10
|
+
RUN apt-get update \
|
|
11
|
+
&& apt-get install -y --no-install-recommends gcc libc6-dev \
|
|
12
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
13
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ARG clams_version
|
|
2
|
+
FROM ghcr.io/clamsproject/clams-python:$clams_version
|
|
3
|
+
LABEL org.opencontainers.image.description="clams-python-torch2 image is shipped with clams-python and PyTorch2"
|
|
4
|
+
|
|
5
|
+
RUN pip install --no-cache-dir torch==2.*
|
|
6
|
+
|
|
7
|
+
# PyTorch ships Triton, which JIT-compiles a small host-side CUDA driver shim
|
|
8
|
+
# at runtime -- that needs a C compiler + libc headers. Keep it minimal
|
|
9
|
+
# (gcc + libc6-dev); build-essential is not required.
|
|
10
|
+
RUN apt-get update \
|
|
11
|
+
&& apt-get install -y --no-install-recommends gcc libc6-dev \
|
|
12
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
13
|
+
|
|
@@ -550,6 +550,11 @@ A consumer of the output MMIF can read the resolved revision directly
|
|
|
550
550
|
from the view metadata, with no cross-reference to the app metadata
|
|
551
551
|
required.
|
|
552
552
|
|
|
553
|
+
This ``model`` handling is a specific instance of the general MMIF convention
|
|
554
|
+
for recording runtime configuration; see the view-metadata section of the
|
|
555
|
+
`MMIF specification <https://mmif.clams.ai/1.2.0/>`_ for the definitions of the
|
|
556
|
+
``parameters`` and ``appConfiguration`` fields.
|
|
557
|
+
|
|
553
558
|
What the base class provides
|
|
554
559
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
555
560
|
|
|
@@ -299,6 +299,18 @@ The envelope looks like this:
|
|
|
299
299
|
The output is always raw MMIF, regardless of input format, so downstream
|
|
300
300
|
pipeline steps are unaffected.
|
|
301
301
|
|
|
302
|
+
.. note::
|
|
303
|
+
|
|
304
|
+
The values in the envelope's ``parameters`` block (not to be confused with
|
|
305
|
+
``view.metadata.parameters``, the recorded output field) are interpreted as
|
|
306
|
+
native JSON. Use real numbers, booleans, arrays, and objects (e.g. ``0.7``, ``true``,
|
|
307
|
+
``["a", "b"]``, ``{"B": "bars"}``), not the URL-encoded string form. To
|
|
308
|
+
reproduce a past run from an existing MMIF, copy the target view's
|
|
309
|
+
``appConfiguration`` into the envelope's ``parameters``; it holds the fully
|
|
310
|
+
resolved, native-JSON configuration. Copying from ``view.metadata.parameters``
|
|
311
|
+
is not reliable, since that field is the raw "as typed" transcript and is not
|
|
312
|
+
guaranteed to round-trip.
|
|
313
|
+
|
|
302
314
|
You can still combine the envelope with query string parameters.
|
|
303
315
|
When the same parameter appears in both, the **query string takes priority**,
|
|
304
316
|
which allows quick overrides without editing the parameter file:
|
|
@@ -69,7 +69,7 @@ When you inherit :class:`~clams.app.ClamsApp`, you need to implement
|
|
|
69
69
|
As a developer you can expose different behaviors of the ``annotate()`` method by providing configurable parameters as keyword arguments of the method. For example, you can have the user specify a re-sample rate of an audio file to be analyzed by providing a ``resample_rate`` parameter.
|
|
70
70
|
|
|
71
71
|
.. note::
|
|
72
|
-
These runtime configurations are not part of the MMIF input
|
|
72
|
+
These runtime configurations are not part of the MMIF input. The SDK records them automatically in the output view metadata for reproducibility: the raw user input in ``view.metadata.parameters`` and the fully resolved configuration in ``view.metadata.appConfiguration``. Both fields are defined in the view-metadata section of the `MMIF specification <https://mmif.clams.ai/1.2.0/>`_.
|
|
73
73
|
|
|
74
74
|
.. note::
|
|
75
75
|
Some runtime parameters are managed by the SDK itself rather than declared per-app. The *universal* parameters in :const:`clams.app.ClamsApp.universal_parameters` are one such set; they are auto-added to every CLAMS app. Specialized base classes (see below) add their own SDK-managed parameter sets on top.
|
|
@@ -32,9 +32,17 @@ annotations. See an example below.
|
|
|
32
32
|
|
|
33
33
|
...
|
|
34
34
|
|
|
35
|
-
When you use a configuration parameter in your app, you should also expose it
|
|
35
|
+
When you use a configuration parameter in your app, you should also expose it
|
|
36
36
|
to the user via the app metadata. See :ref:`appmetadata` section for more details.
|
|
37
37
|
|
|
38
|
+
.. note::
|
|
39
|
+
Whichever channel supplies them, the SDK records the runtime parameters in the
|
|
40
|
+
output view metadata: the raw user input (as strings) in
|
|
41
|
+
``view.metadata.parameters``, and the fully refined configuration (defaults filled
|
|
42
|
+
and values cast) in ``view.metadata.appConfiguration``. See the view-metadata
|
|
43
|
+
section of the `MMIF specification <https://mmif.clams.ai/1.2.0/>`_ for the
|
|
44
|
+
authoritative definitions of these two fields.
|
|
45
|
+
|
|
38
46
|
As HTTP Server
|
|
39
47
|
--------------
|
|
40
48
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"``clams-python`` version","``mmif-python`` version","Target MMIF Specification"
|
|
2
|
+
`1.7.4 <https://pypi.org/project/clams-python/1.7.4/>`__,`1.5.3 <https://pypi.org/project/mmif-python/1.5.3/>`__,`1.2.0 <https://mmif.clams.ai/1.2.0/>`__
|
|
2
3
|
`1.7.3 <https://pypi.org/project/clams-python/1.7.3/>`__,`1.5.1 <https://pypi.org/project/mmif-python/1.5.1/>`__,`1.2.0 <https://mmif.clams.ai/1.2.0/>`__
|
|
3
4
|
`1.7.2 <https://pypi.org/project/clams-python/1.7.2/>`__,`1.5.1 <https://pypi.org/project/mmif-python/1.5.1/>`__,`1.2.0 <https://mmif.clams.ai/1.2.0/>`__
|
|
4
5
|
`1.7.1 <https://pypi.org/project/clams-python/1.7.1/>`__,`1.5.1 <https://pypi.org/project/mmif-python/1.5.1/>`__,`1.2.0 <https://mmif.clams.ai/1.2.0/>`__
|
|
@@ -262,6 +262,34 @@ class TestClamsApp(unittest.TestCase):
|
|
|
262
262
|
self.assertEqual(len(v4.metadata.appConfiguration), 6)
|
|
263
263
|
self.assertEqual(len(v4.metadata.parameters['multivalued_param']), len(str(multiple_values)))
|
|
264
264
|
|
|
265
|
+
def test_add_parameters_to_metadata_len_branch(self):
|
|
266
|
+
# recording branches purely on the number of values, uniformly for
|
|
267
|
+
# declared and undeclared params (issue #296)
|
|
268
|
+
m = Mmif(self.in_mmif)
|
|
269
|
+
|
|
270
|
+
# single value -> bare value, no list brackets
|
|
271
|
+
v = m.new_view()
|
|
272
|
+
self.app.add_parameters_to_metadata(v, {'undeclared': ['solo']})
|
|
273
|
+
self.assertEqual(v.metadata.parameters['undeclared'], 'solo')
|
|
274
|
+
|
|
275
|
+
# multiple values -> serialized list, no data loss
|
|
276
|
+
v = m.new_view()
|
|
277
|
+
self.app.add_parameters_to_metadata(v, {'undeclared_multi': ['a', 'b']})
|
|
278
|
+
self.assertEqual(v.metadata.parameters['undeclared_multi'], str(['a', 'b']))
|
|
279
|
+
|
|
280
|
+
# empty list (only an envelope like {"x": []}/{"x": {}} can produce it)
|
|
281
|
+
# -> treated as unset, skipped, and must not raise IndexError
|
|
282
|
+
v = m.new_view()
|
|
283
|
+
self.app.add_parameters_to_metadata(v, {'empty': []})
|
|
284
|
+
self.assertNotIn('empty', v.metadata.parameters)
|
|
285
|
+
|
|
286
|
+
# a declared multivalued param given a single value is also recorded clean
|
|
287
|
+
self.app.metadata.add_parameter(
|
|
288
|
+
'mv', 'multivalued', type='string', multivalued=True, default=[])
|
|
289
|
+
v = m.new_view()
|
|
290
|
+
self.app.add_parameters_to_metadata(v, {'mv': ['only']})
|
|
291
|
+
self.assertEqual(v.metadata.parameters['mv'], 'only')
|
|
292
|
+
|
|
265
293
|
def test_app_tags_default_empty(self):
|
|
266
294
|
# apps that don't declare tags should not write an appTags field to view metadata
|
|
267
295
|
self.assertEqual(self.app.metadata.app_tags, [])
|
|
@@ -417,6 +445,55 @@ class TestClamsApp(unittest.TestCase):
|
|
|
417
445
|
self.assertEqual(len(last_view.metadata.contains), 0)
|
|
418
446
|
self.assertEqual(len(last_view.metadata.error), 2)
|
|
419
447
|
|
|
448
|
+
def test_empty_view_becomes_warning_view(self):
|
|
449
|
+
class EmptyClamsApp(clams.app.ClamsApp):
|
|
450
|
+
def _appmetadata(self):
|
|
451
|
+
pass
|
|
452
|
+
def _annotate(self, mmif, **kwargs):
|
|
453
|
+
new_view = mmif.new_view()
|
|
454
|
+
self.sign_view(new_view, kwargs)
|
|
455
|
+
new_view.new_contain(AnnotationTypes.TimeFrame)
|
|
456
|
+
return mmif
|
|
457
|
+
out_mmif = Mmif(EmptyClamsApp().annotate(self.in_mmif))
|
|
458
|
+
self.assertEqual(len(out_mmif.views), 1)
|
|
459
|
+
view = next(iter(out_mmif.views))
|
|
460
|
+
self.assertEqual(len(view.annotations), 0)
|
|
461
|
+
self.assertTrue(any('EmptyOutputWarning' in w for w in view.metadata.warnings))
|
|
462
|
+
|
|
463
|
+
def test_partial_empty_views_are_pruned_without_warning(self):
|
|
464
|
+
class MixedClamsApp(clams.app.ClamsApp):
|
|
465
|
+
def _appmetadata(self):
|
|
466
|
+
pass
|
|
467
|
+
def _annotate(self, mmif, **kwargs):
|
|
468
|
+
populated = mmif.new_view()
|
|
469
|
+
self.sign_view(populated, kwargs)
|
|
470
|
+
populated.new_contain(AnnotationTypes.TimeFrame)
|
|
471
|
+
populated.new_annotation(AnnotationTypes.TimeFrame, start=0, end=1)
|
|
472
|
+
empty = mmif.new_view()
|
|
473
|
+
self.sign_view(empty, kwargs)
|
|
474
|
+
empty.new_contain(AnnotationTypes.TimeFrame)
|
|
475
|
+
return mmif
|
|
476
|
+
out_mmif = Mmif(MixedClamsApp().annotate(self.in_mmif))
|
|
477
|
+
self.assertEqual(len(out_mmif.views), 1)
|
|
478
|
+
view = next(iter(out_mmif.views))
|
|
479
|
+
self.assertEqual(len(view.annotations), 1)
|
|
480
|
+
self.assertFalse(view.has_warnings())
|
|
481
|
+
|
|
482
|
+
def test_self_reported_error_view_is_not_pruned(self):
|
|
483
|
+
class ErroringClamsApp(clams.app.ClamsApp):
|
|
484
|
+
def _appmetadata(self):
|
|
485
|
+
pass
|
|
486
|
+
def _annotate(self, mmif, **kwargs):
|
|
487
|
+
new_view = mmif.new_view()
|
|
488
|
+
self.sign_view(new_view, kwargs)
|
|
489
|
+
new_view.set_error('simulated failure', 'trace')
|
|
490
|
+
return mmif
|
|
491
|
+
out_mmif = Mmif(ErroringClamsApp().annotate(self.in_mmif))
|
|
492
|
+
self.assertEqual(len(out_mmif.views), 1)
|
|
493
|
+
view = next(iter(out_mmif.views))
|
|
494
|
+
self.assertTrue(view.has_error())
|
|
495
|
+
self.assertFalse(view.has_warnings())
|
|
496
|
+
|
|
420
497
|
def test_gpu_mem_fields_default_zero(self):
|
|
421
498
|
"""GPU memory fields default to 0."""
|
|
422
499
|
metadata = AppMetadata(
|
|
@@ -236,6 +236,19 @@ class TestRestifierEnvelope(unittest.TestCase):
|
|
|
236
236
|
self.assertEqual(res.status_code, 200)
|
|
237
237
|
Mmif(res.get_data(as_text=True))
|
|
238
238
|
|
|
239
|
+
def test_empty_collection_param_does_not_crash(self):
|
|
240
|
+
# {"x": []} / {"x": {}} normalize to an empty list; recording must skip
|
|
241
|
+
# the param instead of raising IndexError on v[0] (issue #296)
|
|
242
|
+
for empty in ([], {}):
|
|
243
|
+
envelope_str = create_envelope(
|
|
244
|
+
self.mmif_str, {'emptyparam': empty}
|
|
245
|
+
)
|
|
246
|
+
res = self.client.post('/', data=envelope_str)
|
|
247
|
+
self.assertEqual(res.status_code, 200)
|
|
248
|
+
out = Mmif(res.get_data(as_text=True))
|
|
249
|
+
for view in out.views:
|
|
250
|
+
self.assertNotIn('emptyparam', view.metadata.parameters)
|
|
251
|
+
|
|
239
252
|
PREFIX = "Invalid input data. See below for validation error."
|
|
240
253
|
|
|
241
254
|
def test_envelope_missing_mmif(self):
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
ARG clams_version
|
|
2
|
-
FROM ghcr.io/clamsproject/clams-python-opencv4:$clams_version
|
|
3
|
-
LABEL org.opencontainers.image.description="clams-python-opencv4-torch2 image is shipped with clams-python, opencv4 (ffmpeg backend), and PyTorch2"
|
|
4
|
-
|
|
5
|
-
RUN pip install --no-cache-dir torch==2.*
|
|
6
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/.dockerignore.template
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/app/requirements.txt.template
RENAMED
|
File without changes
|
{clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/gha/for-clams-team.md.template
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/gha/workflows/publish.yml.template
RENAMED
|
File without changes
|
{clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/utl-tf/__init__.py.template
RENAMED
|
File without changes
|
{clams_python-1.7.3 → clams_python-1.7.4}/clams/develop/templates/utl-tf/timeframe.py.template
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|