Skip to content

Commit 19984ee

Browse files
author
Joel Collins
committed
Added static file directories to extensions
1 parent 71dfcc1 commit 19984ee

File tree

7 files changed

+108
-62
lines changed

7 files changed

+108
-62
lines changed

examples/builder.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import atexit
55
import logging
66

7-
from labthings.server.quick import create_app, property_of
7+
from labthings.server.quick import create_app
8+
from labthings.server.view.builder import property_of
89

910
from components.pdf_component import PdfComponent
1011

examples/simple_extensions.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from labthings.server.find import find_component
1818
from labthings.server import fields
1919
from labthings.core.tasks import taskify
20+
import os
2021

2122
from labthings.server.extensions import BaseExtension
2223

@@ -37,7 +38,12 @@ def ext_on_my_component(component):
3738
logging.info(f"{component} registered and noticed by extension")
3839

3940

40-
example_extension = BaseExtension("org.labthings.examples.extension")
41+
static_folder = os.path.join(os.path.abspath(os.path.dirname(__file__)), "static")
42+
43+
example_extension = BaseExtension(
44+
"org.labthings.examples.extension", static_folder=static_folder
45+
)
46+
4147
example_extension.on_register(ext_on_register)
4248
example_extension.on_component("org.labthings.example.mycomponent", ext_on_my_component)
4349

examples/static/example.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"app": "python-labthings",
3+
"name": "squidward"
4+
}

labthings/server/extensions.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import glob
88

9+
from .view.builder import static_from
910
from ..core.utilities import get_docstring, camel_to_snake, snake_to_spine
1011

1112

@@ -18,7 +19,14 @@ class BaseExtension:
1819

1920
# TODO: Allow adding components to extensions
2021

21-
def __init__(self, name: str, description="", version="0.0.0"):
22+
def __init__(
23+
self,
24+
name: str,
25+
description="",
26+
version="0.0.0",
27+
static_url_path="/static",
28+
static_folder=None,
29+
):
2230
self._views = (
2331
{}
2432
) # Key: Full, Python-safe ID. Val: Original rule, and view class
@@ -44,6 +52,12 @@ def __init__(self, name: str, description="", version="0.0.0"):
4452

4553
self.methods = {}
4654

55+
if static_folder:
56+
self.static_view_class = static_from(static_folder)
57+
self.add_view(self.static_view_class, f"{static_url_path}/<path:path>")
58+
else:
59+
self.static_view_class = None
60+
4761
@property
4862
def views(self):
4963
return self._views

labthings/server/quick.py

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
from flask import Flask
2+
23
from flask_cors import CORS
34

45
from .labthing import LabThing
56
from .exceptions import JSONExceptionHandler
67

7-
from .view import View
8-
from .types import value_to_field, data_dict_to_schema
9-
from .decorators import ThingProperty, PropertySchema, Doc
10-
118

129
def create_app(
1310
import_name,
@@ -66,58 +63,3 @@ def create_app(
6663

6764
return app, labthing
6865

69-
70-
def property_of(
71-
property_object, property_name, name: str = None, readonly=False, description=None
72-
):
73-
74-
# Create a class name
75-
if not name:
76-
name = type(property_object).__name__ + f"_{property_name}"
77-
78-
# Create inner functions
79-
def _get(self):
80-
return getattr(property_object, property_name)
81-
82-
def _post(self, args):
83-
setattr(property_object, property_name, args)
84-
return getattr(property_object, property_name)
85-
86-
def _put(self, args):
87-
getattr(property_object, property_name).update(args)
88-
return getattr(property_object, property_name)
89-
90-
# Generate a basic property class
91-
generated_class = type(
92-
name,
93-
(View, object),
94-
{
95-
"property_object": property_object,
96-
"property_name": property_name,
97-
"get": _get,
98-
},
99-
)
100-
101-
# Override read-write capabilities
102-
if not readonly:
103-
generated_class.post = _post
104-
# Enable PUT requests for dictionaries
105-
if type(getattr(property_object, property_name)) == dict:
106-
generated_class.put = _put
107-
108-
# Add decorators for arguments etc
109-
initial_property_value = getattr(property_object, property_name)
110-
if type(initial_property_value) == dict:
111-
property_schema = data_dict_to_schema(initial_property_value)
112-
else:
113-
property_schema = value_to_field(initial_property_value)
114-
115-
generated_class = PropertySchema(property_schema)(generated_class)
116-
generated_class = ThingProperty(generated_class)
117-
118-
if description:
119-
generated_class = Doc(description=description, summary=description)(
120-
generated_class
121-
)
122-
123-
return generated_class

labthings/server/view/builder.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from labthings.server.types import value_to_field, data_dict_to_schema
2+
from labthings.server.decorators import ThingProperty, PropertySchema, Doc
3+
from . import View
4+
5+
from flask import send_from_directory
6+
import uuid
7+
8+
9+
def property_of(
10+
property_object, property_name, name: str = None, readonly=False, description=None
11+
):
12+
13+
# Create a class name
14+
if not name:
15+
name = type(property_object).__name__ + f"_{property_name}"
16+
17+
# Create inner functions
18+
def _get(self):
19+
return getattr(property_object, property_name)
20+
21+
def _post(self, args):
22+
setattr(property_object, property_name, args)
23+
return getattr(property_object, property_name)
24+
25+
def _put(self, args):
26+
getattr(property_object, property_name).update(args)
27+
return getattr(property_object, property_name)
28+
29+
# Generate a basic property class
30+
generated_class = type(
31+
name,
32+
(View, object),
33+
{
34+
"property_object": property_object,
35+
"property_name": property_name,
36+
"get": _get,
37+
},
38+
)
39+
40+
# Override read-write capabilities
41+
if not readonly:
42+
generated_class.post = _post
43+
# Enable PUT requests for dictionaries
44+
if type(getattr(property_object, property_name)) == dict:
45+
generated_class.put = _put
46+
47+
# Add decorators for arguments etc
48+
initial_property_value = getattr(property_object, property_name)
49+
if type(initial_property_value) == dict:
50+
property_schema = data_dict_to_schema(initial_property_value)
51+
else:
52+
property_schema = value_to_field(initial_property_value)
53+
54+
generated_class = PropertySchema(property_schema)(generated_class)
55+
generated_class = ThingProperty(generated_class)
56+
57+
if description:
58+
generated_class = Doc(description=description, summary=description)(
59+
generated_class
60+
)
61+
62+
return generated_class
63+
64+
65+
def static_from(static_folder: str, name=None):
66+
67+
# Create a class name
68+
if not name:
69+
uid = uuid.uuid4()
70+
name = f"static-{uid}"
71+
72+
# Create inner functions
73+
def _get(self, path):
74+
return send_from_directory(static_folder, path)
75+
76+
# Generate a basic property class
77+
generated_class = type(name, (View, object), {"get": _get,},)
78+
79+
return generated_class

0 commit comments

Comments
 (0)