robotpy-cscore 2027.0.0a3__cp314-cp314-manylinux_2_39_x86_64.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 robotpy-cscore might be problematic. Click here for more details.
- cscore/__init__.py +59 -0
- cscore/__main__.py +152 -0
- cscore/_cscore.cpython-314-x86_64-linux-gnu.so +0 -0
- cscore/_cscore.pyi +1615 -0
- cscore/_init__cscore.py +6 -0
- cscore/_logging.py +12 -0
- cscore/cscore-casters.pc +8 -0
- cscore/cscore-casters.pybind11.json +1 -0
- cscore/cscore.pc +10 -0
- cscore/cvnp/README.md +11 -0
- cscore/cvnp/cvnp.cpp +242 -0
- cscore/cvnp/cvnp.h +434 -0
- cscore/cvnp/cvnp_synonyms.cpp +70 -0
- cscore/cvnp/cvnp_synonyms.h +25 -0
- cscore/grip.py +41 -0
- cscore/imagewriter.py +146 -0
- cscore/py.typed +0 -0
- cscore/src/main.cpp +19 -0
- cscore/trampolines/cs__AxisCamera.hpp +9 -0
- cscore/trampolines/cs__CvSink.hpp +13 -0
- cscore/trampolines/cs__CvSource.hpp +13 -0
- cscore/trampolines/cs__HttpCamera.hpp +9 -0
- cscore/trampolines/cs__ImageSink.hpp +9 -0
- cscore/trampolines/cs__ImageSource.hpp +9 -0
- cscore/trampolines/cs__MjpegServer.hpp +9 -0
- cscore/trampolines/cs__RawEvent.hpp +9 -0
- cscore/trampolines/cs__UsbCamera.hpp +9 -0
- cscore/trampolines/cs__UsbCameraInfo.hpp +9 -0
- cscore/trampolines/cs__VideoCamera.hpp +9 -0
- cscore/trampolines/cs__VideoEvent.hpp +9 -0
- cscore/trampolines/cs__VideoListener.hpp +9 -0
- cscore/trampolines/cs__VideoMode.hpp +9 -0
- cscore/trampolines/cs__VideoProperty.hpp +9 -0
- cscore/trampolines/cs__VideoSink.hpp +9 -0
- cscore/trampolines/cs__VideoSource.hpp +9 -0
- cscore/trampolines/frc__CameraServer.hpp +12 -0
- cscore/version.py +3 -0
- robotpy_cscore-2027.0.0a3.dist-info/METADATA +11 -0
- robotpy_cscore-2027.0.0a3.dist-info/RECORD +42 -0
- robotpy_cscore-2027.0.0a3.dist-info/WHEEL +4 -0
- robotpy_cscore-2027.0.0a3.dist-info/entry_points.txt +3 -0
- robotpy_cscore-2027.0.0a3.dist-info/licenses/LICENSE +51 -0
cscore/imagewriter.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
import time
|
|
3
|
+
import threading
|
|
4
|
+
|
|
5
|
+
import cv2
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger("cscore.storage")
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ImageWriter:
|
|
14
|
+
"""
|
|
15
|
+
Creates a thread that periodically writes images to a specified
|
|
16
|
+
directory. Useful for looking at images after a match has
|
|
17
|
+
completed.
|
|
18
|
+
|
|
19
|
+
The default location is ``/media/sda1/camera``. The folder
|
|
20
|
+
``/media/sda1`` is the default location that USB drives inserted into
|
|
21
|
+
the RoboRIO are mounted at. The USB drive must have a directory in it
|
|
22
|
+
named ``camera``.
|
|
23
|
+
|
|
24
|
+
.. note:: It is recommended to only write images when something useful
|
|
25
|
+
(such as targeting) is happening, otherwise you'll end up
|
|
26
|
+
with a lot of images written to disk that you probably aren't
|
|
27
|
+
interested in.
|
|
28
|
+
|
|
29
|
+
Intended usage is::
|
|
30
|
+
|
|
31
|
+
self.image_writer = ImageWriter()
|
|
32
|
+
|
|
33
|
+
..
|
|
34
|
+
|
|
35
|
+
while True:
|
|
36
|
+
|
|
37
|
+
img = ..
|
|
38
|
+
|
|
39
|
+
if self.logging_enabled:
|
|
40
|
+
self.image_writer.setImage(img)
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
*,
|
|
47
|
+
location_root="/media/sda1/camera",
|
|
48
|
+
capture_period=0.5,
|
|
49
|
+
image_format="jpg"
|
|
50
|
+
):
|
|
51
|
+
"""
|
|
52
|
+
:param location_root: Directory to write images to. A subdirectory
|
|
53
|
+
with the current time will be created, and
|
|
54
|
+
timestamped images will be written to the
|
|
55
|
+
subdirectory.
|
|
56
|
+
:param capture_period: How often to write images to disk
|
|
57
|
+
:param image_format: File extension of files to write
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
self.location_root = os.path.abspath(location_root)
|
|
61
|
+
self.capture_period = capture_period
|
|
62
|
+
self.image_format = image_format
|
|
63
|
+
|
|
64
|
+
self.active = True
|
|
65
|
+
self._location = None
|
|
66
|
+
self.has_image = False
|
|
67
|
+
self.size = None
|
|
68
|
+
|
|
69
|
+
self.lock = threading.Condition()
|
|
70
|
+
self._thread = threading.Thread(target=self._run, daemon=True)
|
|
71
|
+
self._thread.start()
|
|
72
|
+
|
|
73
|
+
def setImage(self, img):
|
|
74
|
+
"""
|
|
75
|
+
Call this function when you wish to write the image to disk. Not
|
|
76
|
+
every image is written to disk. Makes a copy of the image.
|
|
77
|
+
|
|
78
|
+
:param img: A numpy array representing an OpenCV image
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
if not self.active:
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
self.size is None
|
|
86
|
+
or self.size[0] != img.shape[0]
|
|
87
|
+
or self.size[1] != img.shape[1]
|
|
88
|
+
):
|
|
89
|
+
h, w = img.shape[:2]
|
|
90
|
+
self.size = (h, w)
|
|
91
|
+
|
|
92
|
+
self.out1 = np.empty((h, w, 3), dtype=np.uint8)
|
|
93
|
+
self.out2 = np.empty((h, w, 3), dtype=np.uint8)
|
|
94
|
+
|
|
95
|
+
with self.lock:
|
|
96
|
+
cv2.copyMakeBorder(
|
|
97
|
+
img, 0, 0, 0, 0, cv2.BORDER_CONSTANT, value=(0, 0, 255), dst=self.out1
|
|
98
|
+
)
|
|
99
|
+
self.has_image = True
|
|
100
|
+
self.lock.notify()
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def location(self):
|
|
104
|
+
if self._location is None:
|
|
105
|
+
# This assures that we only log when a USB memory stick is plugged in
|
|
106
|
+
if not os.path.exists(self.location_root):
|
|
107
|
+
raise OSError(
|
|
108
|
+
"Logging disabled, %s does not exist" % self.location_root
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Can't do this when program starts, time might be wrong. Ideally by now the DS
|
|
112
|
+
# has connected, so the time will be correct
|
|
113
|
+
self._location = self.location_root + "/%s" % time.strftime(
|
|
114
|
+
"%Y-%m-%d %H.%M.%S"
|
|
115
|
+
)
|
|
116
|
+
logger.info("Logging to %s", self._location)
|
|
117
|
+
os.makedirs(self._location, exist_ok=True)
|
|
118
|
+
|
|
119
|
+
return self._location
|
|
120
|
+
|
|
121
|
+
def _run(self):
|
|
122
|
+
last = time.time()
|
|
123
|
+
|
|
124
|
+
logger.info("Storage thread started")
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
while True:
|
|
128
|
+
with self.lock:
|
|
129
|
+
now = time.time()
|
|
130
|
+
while (not self.has_image) or (now - last) < self.capture_period:
|
|
131
|
+
self.lock.wait()
|
|
132
|
+
now = time.time()
|
|
133
|
+
|
|
134
|
+
self.out2, self.out1 = self.out1, self.out2
|
|
135
|
+
self.has_image = False
|
|
136
|
+
|
|
137
|
+
fname = "%s/%.2f.%s" % (self.location, now, self.image_format)
|
|
138
|
+
cv2.imwrite(fname, self.out2)
|
|
139
|
+
|
|
140
|
+
last = now
|
|
141
|
+
|
|
142
|
+
except OSError as e:
|
|
143
|
+
logger.error("Error logging images: %s", e)
|
|
144
|
+
|
|
145
|
+
logger.warn("Storage thread exited")
|
|
146
|
+
self.active = False
|
cscore/py.typed
ADDED
|
File without changes
|
cscore/src/main.cpp
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
#include <semiwrap_init.cscore._cscore.hpp>
|
|
3
|
+
|
|
4
|
+
#include "cscore_cpp.h"
|
|
5
|
+
|
|
6
|
+
SEMIWRAP_PYBIND11_MODULE(m) {
|
|
7
|
+
initWrapper(m);
|
|
8
|
+
|
|
9
|
+
static int unused; // the capsule needs something to reference
|
|
10
|
+
py::capsule cleanup(&unused, [](void *) {
|
|
11
|
+
// don't release gil until after calling this
|
|
12
|
+
cs::SetDefaultLogger(20 /* WPI_LOG_INFO */);
|
|
13
|
+
|
|
14
|
+
// but this MUST release the gil, or deadlock may occur
|
|
15
|
+
py::gil_scoped_release __release;
|
|
16
|
+
CS_Shutdown();
|
|
17
|
+
});
|
|
18
|
+
m.add_object("_cleanup", cleanup);
|
|
19
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This file is autogenerated. DO NOT EDIT
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
#include <semiwrap.h>
|
|
5
|
+
|
|
6
|
+
// wrapped header
|
|
7
|
+
|
|
8
|
+
#include <cscore_cv.h>
|
|
9
|
+
|
|
10
|
+
// from extra_includes
|
|
11
|
+
#include <opencv2/core/core.hpp>
|
|
12
|
+
#include <cvnp/cvnp.h>
|
|
13
|
+
#error "cs::CvSink does not have a trampoline"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// This file is autogenerated. DO NOT EDIT
|
|
2
|
+
|
|
3
|
+
#pragma once
|
|
4
|
+
#include <semiwrap.h>
|
|
5
|
+
|
|
6
|
+
// wrapped header
|
|
7
|
+
|
|
8
|
+
#include <cscore_cv.h>
|
|
9
|
+
|
|
10
|
+
// from extra_includes
|
|
11
|
+
#include <opencv2/core/core.hpp>
|
|
12
|
+
#include <cvnp/cvnp.h>
|
|
13
|
+
#error "cs::CvSource does not have a trampoline"
|
cscore/version.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: robotpy-cscore
|
|
3
|
+
Version: 2027.0.0a3
|
|
4
|
+
Summary: RobotPy bindings for cscore image processing library
|
|
5
|
+
Project-URL: Source code, https://github.com/robotpy/mostrobotpy
|
|
6
|
+
Author-email: RobotPy Development Team <robotpy@googlegroups.com>
|
|
7
|
+
License-Expression: BSD-3-Clause
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: pyntcore==2027.0.0a3
|
|
10
|
+
Requires-Dist: robotpy-wpinet==2027.0.0a3
|
|
11
|
+
Requires-Dist: robotpy-wpiutil==2027.0.0a3
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
cscore/__init__.py,sha256=xWxHJBSUnPL21pKSgOSup8k5NClz8xUb-fANf4VGPLI,1056
|
|
2
|
+
cscore/__main__.py,sha256=lg7P4Dq6g5sJOcgDICENfjQp43AC-tg6IY99SfCvbcc,3984
|
|
3
|
+
cscore/_logging.py,sha256=FBz3zqXozXiMVB27nXH_65gN9eziUyrhso9pQhcIBdw,321
|
|
4
|
+
cscore/grip.py,sha256=CG4yAHNzAn1JbXoChKO_wblbnNoAuDDaLA9ipp0Tclo,1001
|
|
5
|
+
cscore/imagewriter.py,sha256=ZKvK0zLDj_OBl1KkGT79w_rBiI-bEAeetG6FEnTpHV8,4391
|
|
6
|
+
cscore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
cscore/version.py,sha256=HhBxA53rMU6cMc_GaF2D5zBRbhBLuGI9pyDJ1WV4SDE,90
|
|
8
|
+
cscore/cvnp/README.md,sha256=tjM2hm7INpdQZRPHRmpxTPj23-k4vkGbTlbaBTunN1Q,1164
|
|
9
|
+
cscore/cvnp/cvnp.cpp,sha256=9q5YWv53QyG5pRcOyJCOMEFQJSsUeYRklfgLi9amELU,8974
|
|
10
|
+
cscore/cvnp/cvnp.h,sha256=YgTLCL73KZU3kNUBDUxxYie_kP9nMniMPkNnBrTgPwU,14503
|
|
11
|
+
cscore/cvnp/cvnp_synonyms.cpp,sha256=CdsCtg3Vpl7-kpjpPONhPvsa_9giTvns_xTgtnby4WQ,2350
|
|
12
|
+
cscore/cvnp/cvnp_synonyms.h,sha256=g1oNmv1OTA3TXgg_54JqAwCg43slzenrAet3M-ipEv4,565
|
|
13
|
+
cscore/src/main.cpp,sha256=q4TR_AA_DNmRdPQuljjgLLbrx_CHLMr06qp37oTON4w,529
|
|
14
|
+
cscore/_cscore.cpython-314-x86_64-linux-gnu.so,sha256=NvjX_Azjzq5aUQpsBa3JRqg-QFdtmc9KDEWDwuuJs5g,25325760
|
|
15
|
+
cscore/_cscore.pyi,sha256=xgNao_3Z0rmHedEgzPTVF2X4bp1pht91MQfODoKHW4k,55761
|
|
16
|
+
cscore/_init__cscore.py,sha256=YO5GPjYpB9XMx4NwdPef9WccC-ENQDaV6j3vFPB4R8w,150
|
|
17
|
+
cscore/cscore-casters.pc,sha256=SW2qtGa0plJ64Tu9BA8uDStrQzRGZ1g0GdbDvW0CtG8,192
|
|
18
|
+
cscore/cscore-casters.pybind11.json,sha256=OhrB1ZkzUlHqaL5_tPr0hvifkq13qZZ2pbXVSprxLho,89
|
|
19
|
+
cscore/cscore.pc,sha256=Q4h5Dxj9rSaf2Mrhn3rV0Vm0fgiQITeGyf64bSfbxyk,284
|
|
20
|
+
cscore/trampolines/cs__AxisCamera.hpp,sha256=o7uVmn8X0933zdNSocRON1hAUDm0UC2g6e3AyYknpnk,173
|
|
21
|
+
cscore/trampolines/cs__CvSink.hpp,sha256=TII8RcbzjH8j6if-9LwiUi8iaVSupp9r618CyA2Z7no,249
|
|
22
|
+
cscore/trampolines/cs__CvSource.hpp,sha256=il9Kc_GVmxpz2xcY16DgzY8QbqtLyZiFYuPAKOGWg0o,251
|
|
23
|
+
cscore/trampolines/cs__HttpCamera.hpp,sha256=7kltdI-FLhaw4Ovk_YCFo1BByCCmvyxWiZH3BP-gJPg,173
|
|
24
|
+
cscore/trampolines/cs__ImageSink.hpp,sha256=dqhelXoMeyhn3k1ahZpbjKjARE0HVSrwZqP5495WYvw,172
|
|
25
|
+
cscore/trampolines/cs__ImageSource.hpp,sha256=DnwYvzjm3gbyBP32NHzfY8WcUcQP0qxZwJCAuzSd6R8,174
|
|
26
|
+
cscore/trampolines/cs__MjpegServer.hpp,sha256=rwJ-c9rg62ga2fTet1dnFqFXlStDjEgtuU0AJ5owflA,174
|
|
27
|
+
cscore/trampolines/cs__RawEvent.hpp,sha256=6tID7fzfs99lEplF2Ih3mr66MbnCR3ujL6EIeFiGs9s,172
|
|
28
|
+
cscore/trampolines/cs__UsbCamera.hpp,sha256=0pybyew_LeArqaJuGiAVPc9Ko9RhfYlG3v94b7zyv5s,172
|
|
29
|
+
cscore/trampolines/cs__UsbCameraInfo.hpp,sha256=da-_-ITi6u83gmf_Y17ZbjaKGUyA_CA4MgHCyr-_C6Y,177
|
|
30
|
+
cscore/trampolines/cs__VideoCamera.hpp,sha256=PoKi0HdLNdDQrPy5aTcmWGzZXGM6TYmHptr-95uF6cw,174
|
|
31
|
+
cscore/trampolines/cs__VideoEvent.hpp,sha256=y2HgZExCuRPiUrAAM3Wf7BfYGfMsZOkil9nOHEqi3Yg,173
|
|
32
|
+
cscore/trampolines/cs__VideoListener.hpp,sha256=bj91DPXOebMKluv1Guo69sO8RR49XbwojQekR4CmAR8,176
|
|
33
|
+
cscore/trampolines/cs__VideoMode.hpp,sha256=5aZCNutaJ3xc2EuoRd_XQzKMpWixfXi82qNplRfE5aA,173
|
|
34
|
+
cscore/trampolines/cs__VideoProperty.hpp,sha256=6ypbrQIzLhZSLhBqnfxGchuBbPP7QBWn_m0y2iof4lE,176
|
|
35
|
+
cscore/trampolines/cs__VideoSink.hpp,sha256=nq3nr47D8OCOYYl9XMCD1lDzUKtOKb8qZPYJHTGCFhY,172
|
|
36
|
+
cscore/trampolines/cs__VideoSource.hpp,sha256=txLjYiPmd1PQXm5WZ11j_CbJZcRAE9hcQVWGL8yc-Vs,174
|
|
37
|
+
cscore/trampolines/frc__CameraServer.hpp,sha256=QOD0jYRW4_9PCJLXIcIDTKevnFj9-iO2MxLki0uvdH8,236
|
|
38
|
+
robotpy_cscore-2027.0.0a3.dist-info/METADATA,sha256=R2tXv1rniJjWfY7wL8KhxFVNirlYu8ptrgkC4xMHMLw,432
|
|
39
|
+
robotpy_cscore-2027.0.0a3.dist-info/WHEEL,sha256=bEAjktRbE_07UBQ6mHuKME1IbS2HwPj_aqXCz81sWEw,100
|
|
40
|
+
robotpy_cscore-2027.0.0a3.dist-info/entry_points.txt,sha256=MTVv-2rIw51vWKhX4bVj581sChRKQvZp9WTUlp3mGiY,53
|
|
41
|
+
robotpy_cscore-2027.0.0a3.dist-info/licenses/LICENSE,sha256=sH4JB8OjTOdUoAPcybggUhhjphTHQWR9M8uoT3v8u5w,3087
|
|
42
|
+
robotpy_cscore-2027.0.0a3.dist-info/RECORD,,
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
|
|
2
|
+
Copyright (c) 2017 Dustin Spicuzza
|
|
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
|
+
* Redistributions of source code must retain the above copyright
|
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
|
8
|
+
* Redistributions in binary form must reproduce the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
|
10
|
+
documentation and/or other materials provided with the distribution.
|
|
11
|
+
* Neither the name of RobotPy nor the
|
|
12
|
+
names of its contributors may be used to endorse or promote products
|
|
13
|
+
derived from this software without specific prior written permission.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY ROBOTPY AND CONTRIBUTORS``AS IS'' AND ANY
|
|
16
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
17
|
+
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
|
18
|
+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ROBOTPY OR CONTRIBUTORS BE LIABLE FOR
|
|
19
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
20
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
21
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
22
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
23
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
24
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
25
|
+
|
|
26
|
+
Code for for cscore and other FIRST libraries use the following license:
|
|
27
|
+
|
|
28
|
+
* Copyright (c) 2016 FIRST
|
|
29
|
+
* All rights reserved.
|
|
30
|
+
*
|
|
31
|
+
* Redistribution and use in source and binary forms, with or without
|
|
32
|
+
* modification, are permitted provided that the following conditions are met:
|
|
33
|
+
* * Redistributions of source code must retain the above copyright
|
|
34
|
+
* notice, this list of conditions and the following disclaimer.
|
|
35
|
+
* * Redistributions in binary form must reproduce the above copyright
|
|
36
|
+
* notice, this list of conditions and the following disclaimer in the
|
|
37
|
+
* documentation and/or other materials provided with the distribution.
|
|
38
|
+
* * Neither the name of the FIRST nor the
|
|
39
|
+
* names of its contributors may be used to endorse or promote products
|
|
40
|
+
* derived from this software without specific prior written permission.
|
|
41
|
+
*
|
|
42
|
+
* THIS SOFTWARE IS PROVIDED BY FIRST AND CONTRIBUTORS``AS IS'' AND ANY
|
|
43
|
+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
44
|
+
* WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
|
45
|
+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
|
|
46
|
+
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
47
|
+
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
48
|
+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
49
|
+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
50
|
+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
51
|
+
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|