Updated to new LabThings structure
This commit is contained in:
parent
304e620143
commit
5139b24ffe
14 changed files with 99 additions and 274 deletions
|
|
@ -37,8 +37,8 @@ For example, if you are creating an API route, in which you expect parameters ``
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from labthings.server.schema import Schema
|
from labthings.schema import Schema
|
||||||
from labthings.server import fields
|
from labthings import fields
|
||||||
|
|
||||||
class UserSchema(Schema):
|
class UserSchema(Schema):
|
||||||
name = fields.String(required=True)
|
name = fields.String(required=True)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
Basic extension structure
|
Basic extension structure
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
An extension starts as a simple instance of :py:class:`labthings.server.extensions.BaseExtension`.
|
An extension starts as a simple instance of :py:class:`labthings.extensions.BaseExtension`.
|
||||||
Each extension is described by a single ``BaseExtension`` instance, containing any number of methods, API views, and additional hardware components.
|
Each extension is described by a single ``BaseExtension`` instance, containing any number of methods, API views, and additional hardware components.
|
||||||
|
|
||||||
In order to access the currently running microscope object, use the :py:func:`labthings.server.find.find_component` function, with the argument ``"org.openflexure.microscope"``. Likewise, any new components attached by other extensions can be found using their full name, as above.
|
In order to access the currently running microscope object, use the :py:func:`labthings.find_component` function, with the argument ``"org.openflexure.microscope"``. Likewise, any new components attached by other extensions can be found using their full name, as above.
|
||||||
|
|
||||||
A simple extension file, with no API views but application-available methods may look like:
|
A simple extension file, with no API views but application-available methods may look like:
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@ Once this extension is loaded, any other extensions will have access to your met
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
from labthings.server.find import find_extension
|
from labthings import find_extension
|
||||||
|
|
||||||
def test_extension_method():
|
def test_extension_method():
|
||||||
# Find your extension. Returns None if it hasn't been found.
|
# Find your extension. Returns None if it hasn't been found.
|
||||||
|
|
@ -29,7 +29,7 @@ Once this extension is loaded, any other extensions will have access to your met
|
||||||
Subclassing ``BaseExtension``
|
Subclassing ``BaseExtension``
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
The syntax used above allows novice programmers to easily start building extensions, without having to deal with subclassing. However, for more complex extensions which require persistent state, subclassing :py:class:`labthings.server.extensions.BaseExtension` is recommended.
|
The syntax used above allows novice programmers to easily start building extensions, without having to deal with subclassing. However, for more complex extensions which require persistent state, subclassing :py:class:`labthings.extensions.BaseExtension` is recommended.
|
||||||
|
|
||||||
The same simple extension as seen above can be written using subclassing:
|
The same simple extension as seen above can be written using subclassing:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ An example of a long running task may look like:
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
...
|
...
|
||||||
from labthings.server.view import ActionView
|
from labthings import ActionView
|
||||||
|
|
||||||
class SlowAPI(ActionView):
|
class SlowAPI(ActionView):
|
||||||
def post(self):
|
def post(self):
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ class ZipObjectDescription:
|
||||||
def close(self):
|
def close(self):
|
||||||
logging.debug(self.fp.name)
|
logging.debug(self.fp.name)
|
||||||
self.fp.close()
|
self.fp.close()
|
||||||
|
if os.path.exists(self.fp.name):
|
||||||
os.unlink(self.fp.name)
|
os.unlink(self.fp.name)
|
||||||
|
|
||||||
assert not os.path.exists(self.fp.name)
|
assert not os.path.exists(self.fp.name)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "openflexure-microscope-jsclient",
|
"name": "openflexure-microscope-jsclient",
|
||||||
"version": "2.3.0",
|
"version": "2.4.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
||||||
|
|
@ -1,209 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
class="progress uk-margin-top uk-margin-horizontal-remove uk-padding-remove"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
v-if="progress"
|
|
||||||
class="determinate"
|
|
||||||
:style="barWidthFromProgress"
|
|
||||||
></div>
|
|
||||||
<div v-else class="indeterminate"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="uk-button uk-button-danger uk-form-small uk-float-right uk-width-1-1"
|
|
||||||
@click="terminateTask()"
|
|
||||||
>
|
|
||||||
Terminate
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "TaskProgress",
|
|
||||||
|
|
||||||
props: {
|
|
||||||
taskId: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
pollInterval: {
|
|
||||||
type: Number,
|
|
||||||
required: false,
|
|
||||||
default: 500
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data: function() {
|
|
||||||
return {
|
|
||||||
polling: null,
|
|
||||||
progress: null
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
barWidthFromProgress: function() {
|
|
||||||
var progress = this.progress <= 100 ? this.progress : 100;
|
|
||||||
var styleString = `width: ${progress}%`;
|
|
||||||
return styleString;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
created() {
|
|
||||||
this.polling = setInterval(() => {
|
|
||||||
this.pollProgress();
|
|
||||||
}, this.pollInterval);
|
|
||||||
},
|
|
||||||
|
|
||||||
beforeDestroy() {
|
|
||||||
clearInterval(this.polling);
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
pollProgress: function() {
|
|
||||||
console.log("Starting progress polling");
|
|
||||||
axios
|
|
||||||
.get(`${this.$store.getters.uriV2}/tasks/${this.taskId}`)
|
|
||||||
.then(response => {
|
|
||||||
console.log("PROGRESS RESPONSE: ", response.data.progress);
|
|
||||||
this.progress = response.data.progress;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
terminateTask: function() {
|
|
||||||
axios
|
|
||||||
.delete(`${this.$store.getters.uriV2}/tasks/${this.taskId}`)
|
|
||||||
.then(response => {
|
|
||||||
console.log("TERMINATION RESPONSE: ", response.data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
@import "../../assets/less/theme.less";
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
position: relative;
|
|
||||||
height: 5px;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
background-color: rgba(180, 180, 180, 0.15);
|
|
||||||
border-radius: 2px;
|
|
||||||
background-clip: padding-box;
|
|
||||||
margin: 0.5rem 0 1rem 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress .determinate {
|
|
||||||
position: absolute;
|
|
||||||
background-color: inherit;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
transition: width 0.3s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress .indeterminate,
|
|
||||||
.progress .determinate {
|
|
||||||
background-color: @global-primary-background;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hook-inverse() {
|
|
||||||
.progress .indeterminate,
|
|
||||||
.progress .determinate {
|
|
||||||
background-color: @inverse-primary-muted-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress .indeterminate:before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
background-color: inherit;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
will-change: left, right;
|
|
||||||
-webkit-animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395)
|
|
||||||
infinite;
|
|
||||||
animation: indeterminate 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress .indeterminate:after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
background-color: inherit;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
will-change: left, right;
|
|
||||||
-webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
|
||||||
infinite;
|
|
||||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
|
|
||||||
infinite;
|
|
||||||
-webkit-animation-delay: 1.15s;
|
|
||||||
animation-delay: 1.15s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes indeterminate {
|
|
||||||
0% {
|
|
||||||
left: -35%;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
60% {
|
|
||||||
left: 100%;
|
|
||||||
right: -90%;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
left: 100%;
|
|
||||||
right: -90%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes indeterminate {
|
|
||||||
0% {
|
|
||||||
left: -35%;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
60% {
|
|
||||||
left: 100%;
|
|
||||||
right: -90%;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
left: 100%;
|
|
||||||
right: -90%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@-webkit-keyframes indeterminate-short {
|
|
||||||
0% {
|
|
||||||
left: -200%;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
60% {
|
|
||||||
left: 107%;
|
|
||||||
right: -8%;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
left: 107%;
|
|
||||||
right: -8%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes indeterminate-short {
|
|
||||||
0% {
|
|
||||||
left: -200%;
|
|
||||||
right: 100%;
|
|
||||||
}
|
|
||||||
60% {
|
|
||||||
left: 107%;
|
|
||||||
right: -8%;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
left: 107%;
|
|
||||||
right: -8%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -90,6 +90,7 @@ export default {
|
||||||
data: function() {
|
data: function() {
|
||||||
return {
|
return {
|
||||||
taskId: null,
|
taskId: null,
|
||||||
|
taskUrl: null,
|
||||||
polling: null,
|
polling: null,
|
||||||
progress: null,
|
progress: null,
|
||||||
taskStarted: false,
|
taskStarted: false,
|
||||||
|
|
@ -150,6 +151,7 @@ export default {
|
||||||
// Fetch the task ID
|
// Fetch the task ID
|
||||||
console.log("Task ID: " + response.data.id);
|
console.log("Task ID: " + response.data.id);
|
||||||
this.taskId = response.data.id;
|
this.taskId = response.data.id;
|
||||||
|
this.taskUrl = response.data.href;
|
||||||
// Start the store polling TaskId for success
|
// Start the store polling TaskId for success
|
||||||
this.taskRunning = true;
|
this.taskRunning = true;
|
||||||
this.$emit("taskRunning", this.taskId);
|
this.$emit("taskRunning", this.taskId);
|
||||||
|
|
@ -192,12 +194,12 @@ export default {
|
||||||
var checkCondition = (resolve, reject) => {
|
var checkCondition = (resolve, reject) => {
|
||||||
// If the condition is met, we're done!
|
// If the condition is met, we're done!
|
||||||
axios
|
axios
|
||||||
.get(`${this.$store.getters.uriV2}/tasks/${taskId}`)
|
.get(this.taskUrl)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
console.log(response.data.status);
|
console.log(response.data.status);
|
||||||
var result = response.data.status;
|
var result = response.data.status;
|
||||||
// If the task ends with success
|
// If the task ends with success
|
||||||
if (result == "success") {
|
if (result == "completed") {
|
||||||
resolve(response.data);
|
resolve(response.data);
|
||||||
}
|
}
|
||||||
// If task ends with an error
|
// If task ends with an error
|
||||||
|
|
@ -206,16 +208,10 @@ export default {
|
||||||
reject(new Error(response.data.return));
|
reject(new Error(response.data.return));
|
||||||
}
|
}
|
||||||
// If task ends with termination
|
// If task ends with termination
|
||||||
else if (result == "terminated") {
|
else if (result == "cancelled") {
|
||||||
// Pass a generic termination error back with reject
|
// Pass a generic termination error back with reject
|
||||||
reject(new Error("Task terminated"));
|
reject(new Error("Task cancelled"));
|
||||||
}
|
}
|
||||||
// If task ends in any other way
|
|
||||||
else if (result != "running") {
|
|
||||||
// Pass status string as error
|
|
||||||
reject(new Error(result));
|
|
||||||
}
|
|
||||||
// Didn't match and too much time, reject!
|
|
||||||
else {
|
else {
|
||||||
// Since the task is still running, we can update the progress bar
|
// Since the task is still running, we can update the progress bar
|
||||||
this.progress = response.data.progress;
|
this.progress = response.data.progress;
|
||||||
|
|
@ -232,7 +228,7 @@ export default {
|
||||||
console.log("Starting progress polling");
|
console.log("Starting progress polling");
|
||||||
|
|
||||||
axios
|
axios
|
||||||
.get(`${this.$store.getters.uriV2}/tasks/${this.taskId}`)
|
.get(this.taskUrl)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
console.log("PROGRESS RESPONSE: ", response.data.progress);
|
console.log("PROGRESS RESPONSE: ", response.data.progress);
|
||||||
this.progress = response.data.progress;
|
this.progress = response.data.progress;
|
||||||
|
|
@ -241,7 +237,7 @@ export default {
|
||||||
|
|
||||||
terminateTask: function() {
|
terminateTask: function() {
|
||||||
axios
|
axios
|
||||||
.delete(`${this.$store.getters.uriV2}/tasks/${this.taskId}`)
|
.delete(this.taskUrl)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
console.log("TERMINATION RESPONSE: ", response.data);
|
console.log("TERMINATION RESPONSE: ", response.data);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
onResponse: function(response) {
|
onResponse: function(response) {
|
||||||
this.lastSessionId = response.return.id;
|
this.lastSessionId = response.output.id;
|
||||||
this.downloadUrl = `${this.zipGetterUri}/${this.lastSessionId}`;
|
this.downloadUrl = `${this.zipGetterUri}/${this.lastSessionId}`;
|
||||||
this.downloadReady = true;
|
this.downloadReady = true;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ from openflexure_microscope.api.utilities import get_bool, JsonResponse
|
||||||
from labthings import Schema, fields, find_component
|
from labthings import Schema, fields, find_component
|
||||||
from labthings.views import View, PropertyView
|
from labthings.views import View, PropertyView
|
||||||
from labthings.utilities import description_from_view
|
from labthings.utilities import description_from_view
|
||||||
from labthings.views.marshalling import marshal_with
|
from labthings.marshalling import marshal_with
|
||||||
|
|
||||||
from marshmallow import pre_dump
|
from marshmallow import pre_dump
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,8 @@ class MissingCamera(BaseCamera):
|
||||||
|
|
||||||
if isinstance(output, str):
|
if isinstance(output, str):
|
||||||
output.close()
|
output.close()
|
||||||
|
else:
|
||||||
|
output.flush()
|
||||||
|
|
||||||
# HANDLE STREAM FRAMES
|
# HANDLE STREAM FRAMES
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ class CaptureObject(object):
|
||||||
|
|
||||||
# Store a nice ID
|
# Store a nice ID
|
||||||
self.id = uuid.uuid4() #: str: Unique capture ID
|
self.id = uuid.uuid4() #: str: Unique capture ID
|
||||||
logging.debug("Created StreamObject {}".format(self.id))
|
logging.debug("Created CaptureObject {}".format(self.id))
|
||||||
self.datetime = datetime.datetime.now()
|
self.datetime = datetime.datetime.now()
|
||||||
|
|
||||||
# Create file name. Default to UUID
|
# Create file name. Default to UUID
|
||||||
|
|
@ -151,6 +151,7 @@ class CaptureObject(object):
|
||||||
self.thumb_bytes = None
|
self.thumb_bytes = None
|
||||||
|
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
|
logging.debug(f"Writing to {self}")
|
||||||
self.stream.write(s)
|
self.stream.write(s)
|
||||||
|
|
||||||
def flush(self):
|
def flush(self):
|
||||||
|
|
|
||||||
|
|
@ -354,7 +354,8 @@ class Microscope:
|
||||||
)
|
)
|
||||||
|
|
||||||
# Capture to output object
|
# Capture to output object
|
||||||
logging.info(f"Starting microscope capture {filename}")
|
logging.info(f"Starting microscope capture {output.file}")
|
||||||
|
print(output)
|
||||||
self.camera.capture(
|
self.camera.capture(
|
||||||
output,
|
output,
|
||||||
use_video_port=use_video_port,
|
use_video_port=use_video_port,
|
||||||
|
|
|
||||||
109
poetry.lock
generated
109
poetry.lock
generated
|
|
@ -12,16 +12,34 @@ description = "A pluggable API specification generator. Currently supports the O
|
||||||
name = "apispec"
|
name = "apispec"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
version = "3.3.1"
|
version = "3.3.2"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["PyYAML (>=3.10)", "prance (>=0.11)", "marshmallow (>=2.19.2)", "pytest", "mock", "flake8 (3.8.2)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)", "tox"]
|
dev = ["PyYAML (>=3.10)", "prance (>=0.11)", "marshmallow (>=2.19.2)", "pytest", "mock", "flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)", "tox"]
|
||||||
docs = ["marshmallow (>=2.19.2)", "pyyaml (5.3.1)", "sphinx (3.0.4)", "sphinx-issues (1.2.0)", "sphinx-rtd-theme (0.4.3)"]
|
docs = ["marshmallow (>=2.19.2)", "pyyaml (5.3.1)", "sphinx (3.2.1)", "sphinx-issues (1.2.0)", "sphinx-rtd-theme (0.5.0)"]
|
||||||
lint = ["flake8 (3.8.2)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)"]
|
lint = ["flake8 (3.8.3)", "flake8-bugbear (20.1.4)", "pre-commit (>=2.4,<3.0)"]
|
||||||
tests = ["PyYAML (>=3.10)", "prance (>=0.11)", "marshmallow (>=2.19.2)", "pytest", "mock"]
|
tests = ["PyYAML (>=3.10)", "prance (>=0.11)", "marshmallow (>=2.19.2)", "pytest", "mock"]
|
||||||
validation = ["prance (>=0.11)"]
|
validation = ["prance (>=0.11)"]
|
||||||
yaml = ["PyYAML (>=3.10)"]
|
yaml = ["PyYAML (>=3.10)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
category = "main"
|
||||||
|
description = "Web framework plugins for apispec."
|
||||||
|
name = "apispec-webframeworks"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
version = "0.5.2"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
[package.dependencies.apispec]
|
||||||
|
extras = ["yaml"]
|
||||||
|
version = ">=2.0.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["pytest", "mock", "Flask (1.1.1)", "tornado", "bottle (0.12.17)", "flake8 (3.7.9)", "flake8-bugbear (19.8.0)", "pre-commit (>=1.18,<2.0)", "tox"]
|
||||||
|
lint = ["flake8 (3.7.9)", "flake8-bugbear (19.8.0)", "pre-commit (>=1.18,<2.0)"]
|
||||||
|
tests = ["pytest", "mock", "Flask (1.1.1)", "tornado", "bottle (0.12.17)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
|
|
@ -91,19 +109,25 @@ d = ["aiohttp (>=3.3.2)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Calibration and mapping between stage and camera coordinates in a microscope"
|
description = ""
|
||||||
name = "camera-stage-mapping"
|
name = "camera-stage-mapping"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6,<4.0"
|
python-versions = "^3.6"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
numpy = ">=1.17,<2.0"
|
numpy = "^1.17"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
all = ["opencv-python-headless (>=4.1,<5.0)", "scipy (>=1.4,<2.0)"]
|
all = ["opencv-python-headless (^4.1)", "scipy (^1.4)"]
|
||||||
correlation = ["opencv-python-headless (>=4.1,<5.0)", "scipy (>=1.4,<2.0)"]
|
correlation = ["opencv-python-headless (^4.1)", "scipy (^1.4)"]
|
||||||
|
ipython = []
|
||||||
|
ofmclient = []
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
reference = "3d5afaf2c4ca23bc1fa08938f82048c61c4c3f56"
|
||||||
|
type = "git"
|
||||||
|
url = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git"
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "Python package for providing Mozilla's CA Bundle."
|
description = "Python package for providing Mozilla's CA Bundle."
|
||||||
|
|
@ -181,7 +205,7 @@ description = "A Flask extension adding a decorator for CORS support"
|
||||||
name = "flask-cors"
|
name = "flask-cors"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
version = "3.0.8"
|
version = "3.0.9"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
Flask = ">=0.9"
|
Flask = ">=0.9"
|
||||||
|
|
@ -193,7 +217,7 @@ description = "Barebones websocket extension for Flask, using Pythonthreading fo
|
||||||
name = "flask-threaded-sockets"
|
name = "flask-threaded-sockets"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6,<4.0"
|
python-versions = ">=3.6,<4.0"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
flask = ">=1.1.2,<2.0.0"
|
flask = ">=1.1.2,<2.0.0"
|
||||||
|
|
@ -269,21 +293,27 @@ i18n = ["Babel (>=0.8)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "Python implementation of LabThings, based on the Flask microframework"
|
description = ""
|
||||||
name = "labthings"
|
name = "labthings"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6,<4.0"
|
python-versions = "^3.6"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
Flask = ">=1.1.1,<2.0.0"
|
Flask = "^1.1.1"
|
||||||
apispec = ">=3.2.0,<4.0.0"
|
apispec = "^3.2.0"
|
||||||
flask-cors = ">=3.0.8,<4.0.0"
|
apispec_webframeworks = "^0.5.2"
|
||||||
flask-threaded-sockets = ">=0.2.0,<0.3.0"
|
flask-cors = "^3.0.8"
|
||||||
marshmallow = ">=3.4.0,<4.0.0"
|
flask-threaded-sockets = "^0.3.0"
|
||||||
webargs = ">=6.0.0,<7.0.0"
|
marshmallow = "^3.4.0"
|
||||||
|
webargs = "^6.0.0"
|
||||||
zeroconf = ">=0.24.5,<0.29.0"
|
zeroconf = ">=0.24.5,<0.29.0"
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
reference = "6a0dc427e316f3098efb3a427d50cefdbd7b4c39"
|
||||||
|
type = "git"
|
||||||
|
url = "https://github.com/labthings/python-labthings.git"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
category = "dev"
|
category = "dev"
|
||||||
description = "A fast and thorough lazy object proxy."
|
description = "A fast and thorough lazy object proxy."
|
||||||
|
|
@ -504,7 +534,7 @@ version = "0.14.0"
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "A module to control Raspberry Pi GPIO channels"
|
description = "A module to control Raspberry Pi GPIO channels"
|
||||||
name = "rpi.gpio"
|
name = "rpi.gpio"
|
||||||
optional = false
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
|
||||||
|
|
@ -737,7 +767,7 @@ description = "Pure Python Multicast DNS Service Discovery Library (Bonjour/Avah
|
||||||
name = "zeroconf"
|
name = "zeroconf"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
version = "0.28.0"
|
version = "0.28.3"
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
ifaddr = ">=0.1.7"
|
ifaddr = ">=0.1.7"
|
||||||
|
|
@ -746,7 +776,7 @@ ifaddr = ">=0.1.7"
|
||||||
rpi = ["RPi.GPIO"]
|
rpi = ["RPi.GPIO"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
content-hash = "446a192e461cdf5d1f12697f3c23d2a1b3cd9250cd6e14ccc884a14d674f8f19"
|
content-hash = "fc117ebf7cd7caf196ba86954743940d6c56e636e473c2c1d304808e1568dc8d"
|
||||||
python-versions = "^3.6"
|
python-versions = "^3.6"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
|
|
@ -755,8 +785,12 @@ alabaster = [
|
||||||
{file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
|
{file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
|
||||||
]
|
]
|
||||||
apispec = [
|
apispec = [
|
||||||
{file = "apispec-3.3.1-py2.py3-none-any.whl", hash = "sha256:b65063e11968a8c26dbbe9b4100ee24026a41cc358dd204df279bdedd7d8dea2"},
|
{file = "apispec-3.3.2-py2.py3-none-any.whl", hash = "sha256:a1df9ec6b2cd0edf45039ef025abd7f0660808fa2edf737d3ba1cf5ef1a4625b"},
|
||||||
{file = "apispec-3.3.1.tar.gz", hash = "sha256:f5244ccca33f7a81309f6b3c9d458e33e869050c2d861b9f8cee24b3ad739d2b"},
|
{file = "apispec-3.3.2.tar.gz", hash = "sha256:d23ebd5b71e541e031b02a19db10b5e6d5ef8452c552833e3e1afc836b40b1ad"},
|
||||||
|
]
|
||||||
|
apispec-webframeworks = [
|
||||||
|
{file = "apispec-webframeworks-0.5.2.tar.gz", hash = "sha256:0db35b267914b3f8c562aca0261957dbcb4176f255eacc22520277010818dcf3"},
|
||||||
|
{file = "apispec_webframeworks-0.5.2-py2.py3-none-any.whl", hash = "sha256:482c563abbcc2a261439476cb3f1a7c7284cc997c322c574d48c111643e9c04e"},
|
||||||
]
|
]
|
||||||
appdirs = [
|
appdirs = [
|
||||||
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
|
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
|
||||||
|
|
@ -778,10 +812,7 @@ black = [
|
||||||
{file = "black-18.9b0-py36-none-any.whl", hash = "sha256:817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739"},
|
{file = "black-18.9b0-py36-none-any.whl", hash = "sha256:817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739"},
|
||||||
{file = "black-18.9b0.tar.gz", hash = "sha256:e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"},
|
{file = "black-18.9b0.tar.gz", hash = "sha256:e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"},
|
||||||
]
|
]
|
||||||
camera-stage-mapping = [
|
camera-stage-mapping = []
|
||||||
{file = "camera-stage-mapping-0.1.3.tar.gz", hash = "sha256:048dfd465ca04b9baa7714b4ce8d53a97eecaa41781cf07e4bd8649e6d4d97d0"},
|
|
||||||
{file = "camera_stage_mapping-0.1.3-py3-none-any.whl", hash = "sha256:16d77f550067aa3e6bcf9de3f39d0ba2a4581927aa729d83e5f0e46ac6c81d5d"},
|
|
||||||
]
|
|
||||||
certifi = [
|
certifi = [
|
||||||
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
|
{file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
|
||||||
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
|
{file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
|
||||||
|
|
@ -810,12 +841,12 @@ flask = [
|
||||||
{file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"},
|
{file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"},
|
||||||
]
|
]
|
||||||
flask-cors = [
|
flask-cors = [
|
||||||
{file = "Flask-Cors-3.0.8.tar.gz", hash = "sha256:72170423eb4612f0847318afff8c247b38bd516b7737adfc10d1c2cdbb382d16"},
|
{file = "Flask-Cors-3.0.9.tar.gz", hash = "sha256:6bcfc100288c5d1bcb1dbb854babd59beee622ffd321e444b05f24d6d58466b8"},
|
||||||
{file = "Flask_Cors-3.0.8-py2.py3-none-any.whl", hash = "sha256:f4d97201660e6bbcff2d89d082b5b6d31abee04b1b3003ee073a6fd25ad1d69a"},
|
{file = "Flask_Cors-3.0.9-py2.py3-none-any.whl", hash = "sha256:cee4480aaee421ed029eaa788f4049e3e26d15b5affb6a880dade6bafad38324"},
|
||||||
]
|
]
|
||||||
flask-threaded-sockets = [
|
flask-threaded-sockets = [
|
||||||
{file = "flask_threaded_sockets-0.2.0-py3-none-any.whl", hash = "sha256:e3fc55ccf7f22e801b967f15efd4d30ae8627c1fdc3c27e0195ba1bd369e32e1"},
|
{file = "flask_threaded_sockets-0.3.0-py3-none-any.whl", hash = "sha256:d9d070229ad11e3fdf01148b7d1ea69623c9bcf4b5b3be810d424fd479e2b42c"},
|
||||||
{file = "flask_threaded_sockets-0.2.0.tar.gz", hash = "sha256:e9d2ee66ae1c9c2ac86373510c2a4295e0230109130b7bc6d2499f5cd4140361"},
|
{file = "flask_threaded_sockets-0.3.0.tar.gz", hash = "sha256:3dee7017abe3e70216740997bd8c1d8ca816b3a0908c0a90fdaac00da2fbdedf"},
|
||||||
]
|
]
|
||||||
future = [
|
future = [
|
||||||
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
|
{file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
|
||||||
|
|
@ -844,10 +875,7 @@ jinja2 = [
|
||||||
{file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
|
{file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
|
||||||
{file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"},
|
{file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"},
|
||||||
]
|
]
|
||||||
labthings = [
|
labthings = []
|
||||||
{file = "labthings-0.8.0-py3-none-any.whl", hash = "sha256:133eb1480dc6ea851faa9a16bcf34d075d513935eac82f8da492e6dc5e336b6c"},
|
|
||||||
{file = "labthings-0.8.0.tar.gz", hash = "sha256:3c440c1bb9547858f2dbe6a85746174c6050016a0a86d773d986ca83fbf89874"},
|
|
||||||
]
|
|
||||||
lazy-object-proxy = [
|
lazy-object-proxy = [
|
||||||
{file = "lazy-object-proxy-1.4.3.tar.gz", hash = "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"},
|
{file = "lazy-object-proxy-1.4.3.tar.gz", hash = "sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"},
|
||||||
{file = "lazy_object_proxy-1.4.3-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442"},
|
{file = "lazy_object_proxy-1.4.3-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442"},
|
||||||
|
|
@ -899,6 +927,11 @@ markupsafe = [
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
|
||||||
|
{file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"},
|
||||||
|
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"},
|
||||||
|
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"},
|
||||||
|
{file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"},
|
||||||
|
{file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"},
|
||||||
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
|
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
|
||||||
]
|
]
|
||||||
marshmallow = [
|
marshmallow = [
|
||||||
|
|
@ -1202,6 +1235,6 @@ wrapt = [
|
||||||
{file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"},
|
{file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"},
|
||||||
]
|
]
|
||||||
zeroconf = [
|
zeroconf = [
|
||||||
{file = "zeroconf-0.28.0-py3-none-any.whl", hash = "sha256:8c448ad37ed074ce8811c9eb2765c01714a93f977a1c04fc39fbf6f516b0566f"},
|
{file = "zeroconf-0.28.3-py3-none-any.whl", hash = "sha256:9ae1d9fbb53e1e5b0965a1e60873f99568f0424a03eb28ce793e75c999a8fc50"},
|
||||||
{file = "zeroconf-0.28.0.tar.gz", hash = "sha256:881da2ed3d7c8e0ab59fb1cc8b02b53134351941c4d8d3f3553a96700f257a03"},
|
{file = "zeroconf-0.28.3.tar.gz", hash = "sha256:1a160082ef198884331b04b636132a243a06d3155f6664e96704b6984cbf485c"},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -45,8 +45,8 @@ opencv-python-headless = [
|
||||||
pynpm = "^0.1.2"
|
pynpm = "^0.1.2"
|
||||||
sangaboard = "^0.2"
|
sangaboard = "^0.2"
|
||||||
expiringdict = "^1.2.1"
|
expiringdict = "^1.2.1"
|
||||||
camera-stage-mapping = "^0.1.2"
|
labthings = {git = "https://github.com/labthings/python-labthings.git"}
|
||||||
labthings = "0.8.0"
|
camera-stage-mapping = {git = "https://gitlab.com/openflexure/microscope-extensions/camera-stage-mapping.git", rev = "updated-labthings-imports"}
|
||||||
|
|
||||||
[tool.poetry.extras]
|
[tool.poetry.extras]
|
||||||
rpi = ["RPi.GPIO"]
|
rpi = ["RPi.GPIO"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue