WIP on libraries upgrade
This commit is contained in:
@@ -280,7 +280,7 @@ class PillarServer(BlinkerCompatibleEve):
|
||||
self.encoding_service_client = Zencoder(self.config['ZENCODER_API_KEY'])
|
||||
|
||||
def _config_caching(self):
|
||||
from flask_cache import Cache
|
||||
from flask_caching import Cache
|
||||
self.cache = Cache(self)
|
||||
|
||||
def set_languages(self, translations_folder: pathlib.Path):
|
||||
|
@@ -97,7 +97,7 @@ class ValidateCustomFields(Validator):
|
||||
return False
|
||||
|
||||
try:
|
||||
value = self.convert_properties(value, node_type['dyn_schema'])
|
||||
value = self.convert_properties(value, node_type['dyn_schema']['shema'])
|
||||
except Exception as e:
|
||||
log.warning("Error converting form properties", exc_info=True)
|
||||
|
||||
@@ -107,7 +107,10 @@ class ValidateCustomFields(Validator):
|
||||
if val:
|
||||
# This ensures the modifications made by v's coercion rules are
|
||||
# visible to this validator's output.
|
||||
self.current[field] = v.current
|
||||
#self.current[field] = v.current
|
||||
print('*********')
|
||||
print(valid_properties)
|
||||
#print(v.current)
|
||||
return True
|
||||
|
||||
log.warning('Error validating properties for node %s: %s', self.document, v.errors)
|
||||
@@ -149,39 +152,25 @@ class ValidateCustomFields(Validator):
|
||||
if ip.prefixlen() == 0:
|
||||
self._error(field_name, 'Zero-length prefix is not allowed')
|
||||
|
||||
def _validate_type_binary(self, field_name: str, value: bytes):
|
||||
"""Add support for binary type.
|
||||
# def _validate_coerce(self, coerce, field: str, value):
|
||||
# """Override Cerberus' _validate_coerce method for richer features.
|
||||
#
|
||||
# This now supports named coercion functions (available in Cerberus 1.0+)
|
||||
# and passes the field name to coercion functions as well.
|
||||
# """
|
||||
# if isinstance(coerce, str):
|
||||
# coerce = getattr(self, f'_normalize_coerce_{coerce}')
|
||||
#
|
||||
# try:
|
||||
# return coerce(field, value)
|
||||
# except (TypeError, ValueError):
|
||||
# self._error(field, cerberus.errors.ERROR_COERCION_FAILED.format(field))
|
||||
|
||||
This type was actually introduced in Cerberus 1.0, so we can drop
|
||||
support for this once Eve starts using that version (or newer).
|
||||
def _validator_markdown(self, field, value):
|
||||
"""This is a placeholder.
|
||||
|
||||
Markdown is actually processed in a hook
|
||||
"""
|
||||
|
||||
if not isinstance(value, (bytes, bytearray)):
|
||||
self._error(field_name, f'wrong value type {type(value)}, expected bytes or bytearray')
|
||||
|
||||
def _validate_coerce(self, coerce, field: str, value):
|
||||
"""Override Cerberus' _validate_coerce method for richer features.
|
||||
|
||||
This now supports named coercion functions (available in Cerberus 1.0+)
|
||||
and passes the field name to coercion functions as well.
|
||||
"""
|
||||
if isinstance(coerce, str):
|
||||
coerce = getattr(self, f'_normalize_coerce_{coerce}')
|
||||
|
||||
try:
|
||||
return coerce(field, value)
|
||||
except (TypeError, ValueError):
|
||||
self._error(field, cerberus.errors.ERROR_COERCION_FAILED.format(field))
|
||||
|
||||
def _normalize_coerce_markdown(self, field: str, value):
|
||||
"""Render Markdown from this field into {field}_html.
|
||||
|
||||
The field name MUST NOT end in `_html`. The Markdown is read from this
|
||||
field and the rendered HTML is written to the field `{field}_html`.
|
||||
"""
|
||||
html = pillar.markdown.markdown(value)
|
||||
field_name = pillar.markdown.cache_field_name(field)
|
||||
self.current[field_name] = html
|
||||
return value
|
||||
|
||||
|
||||
@@ -190,12 +179,12 @@ if __name__ == '__main__':
|
||||
|
||||
v = ValidateCustomFields()
|
||||
v.schema = {
|
||||
'foo': {'type': 'string', 'coerce': 'markdown'},
|
||||
'foo': {'type': 'string', 'validator': 'markdown'},
|
||||
'foo_html': {'type': 'string'},
|
||||
'nested': {
|
||||
'type': 'dict',
|
||||
'schema': {
|
||||
'bar': {'type': 'string', 'coerce': 'markdown'},
|
||||
'bar': {'type': 'string', 'validator': 'markdown'},
|
||||
'bar_html': {'type': 'string'},
|
||||
}
|
||||
}
|
||||
|
@@ -155,7 +155,7 @@ organizations_schema = {
|
||||
'description': {
|
||||
'type': 'string',
|
||||
'maxlength': 256,
|
||||
'coerce': 'markdown',
|
||||
'validator': 'markdown',
|
||||
},
|
||||
'_description_html': {'type': 'string'},
|
||||
'website': {
|
||||
@@ -292,7 +292,7 @@ nodes_schema = {
|
||||
},
|
||||
'description': {
|
||||
'type': 'string',
|
||||
'coerce': 'markdown',
|
||||
'validator': 'markdown',
|
||||
},
|
||||
'_description_html': {'type': 'string'},
|
||||
'picture': _file_embedded_schema,
|
||||
@@ -326,8 +326,8 @@ nodes_schema = {
|
||||
},
|
||||
'properties': {
|
||||
'type': 'dict',
|
||||
'valid_properties': True,
|
||||
'required': True,
|
||||
# 'valid_properties': True,
|
||||
'required': True
|
||||
},
|
||||
'permissions': {
|
||||
'type': 'dict',
|
||||
@@ -539,7 +539,7 @@ projects_schema = {
|
||||
},
|
||||
'description': {
|
||||
'type': 'string',
|
||||
'coerce': 'markdown',
|
||||
'validator': 'markdown',
|
||||
},
|
||||
'_description_html': {'type': 'string'},
|
||||
# Short summary for the project
|
||||
@@ -833,4 +833,4 @@ UPSET_ON_PUT = False # do not create new document on PUT of non-existant URL.
|
||||
X_DOMAINS = '*'
|
||||
X_ALLOW_CREDENTIALS = True
|
||||
X_HEADERS = 'Authorization'
|
||||
XML = False
|
||||
RENDERERS = ['eve.render.JSONRenderer']
|
||||
|
@@ -12,7 +12,7 @@ ATTACHMENT_SLUG_REGEX = r'[a-zA-Z0-9_\-]+'
|
||||
attachments_embedded_schema = {
|
||||
'type': 'dict',
|
||||
# TODO: will be renamed to 'keyschema' in Cerberus 1.0
|
||||
'propertyschema': {
|
||||
'keyschema': {
|
||||
'type': 'string',
|
||||
'regex': '^%s$' % ATTACHMENT_SLUG_REGEX,
|
||||
},
|
||||
|
@@ -7,7 +7,7 @@ node_type_comment = {
|
||||
'type': 'string',
|
||||
'minlength': 5,
|
||||
'required': True,
|
||||
'coerce': 'markdown',
|
||||
'validator': 'markdown',
|
||||
},
|
||||
'_content_html': {'type': 'string'},
|
||||
'status': {
|
||||
|
@@ -3,7 +3,7 @@ node_type_group = {
|
||||
'description': 'Folder node type',
|
||||
'parent': ['group', 'project'],
|
||||
'dyn_schema': {
|
||||
# Used for sorting within the context of a group
|
||||
|
||||
'order': {
|
||||
'type': 'integer'
|
||||
},
|
||||
@@ -20,7 +20,8 @@ node_type_group = {
|
||||
'notes': {
|
||||
'type': 'string',
|
||||
'maxlength': 256,
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
'form_schema': {
|
||||
'url': {'visible': False},
|
||||
|
@@ -9,7 +9,7 @@ node_type_post = {
|
||||
'minlength': 5,
|
||||
'maxlength': 90000,
|
||||
'required': True,
|
||||
'coerce': 'markdown',
|
||||
'validator': 'markdown',
|
||||
},
|
||||
'_content_html': {'type': 'string'},
|
||||
'status': {
|
||||
|
@@ -8,6 +8,7 @@ import werkzeug.exceptions as wz_exceptions
|
||||
from bson import ObjectId
|
||||
from flask import current_app, Blueprint, request
|
||||
|
||||
import pillar.markdown
|
||||
from pillar.api.activities import activity_subscribe, activity_object_add
|
||||
from pillar.api.node_types import PILLAR_NAMED_NODE_TYPES
|
||||
from pillar.api.file_storage_backends.gcs import update_file_name
|
||||
@@ -400,6 +401,40 @@ def textures_sort_files(nodes):
|
||||
texture_sort_files(node)
|
||||
|
||||
|
||||
def parse_markdown(node, original=None):
|
||||
projects_collection = current_app.data.driver.db['projects']
|
||||
project = projects_collection.find_one({'_id': node['project']}, {'node_types': 1})
|
||||
# Query node type directly using the key
|
||||
node_type = next(nt for nt in project['node_types']
|
||||
if nt['name'] == node['node_type'])
|
||||
schema = current_app.config['DOMAIN']['nodes']['schema']
|
||||
schema['properties'] = node_type['dyn_schema']
|
||||
|
||||
def find_markdown_fields(schema, node):
|
||||
"""Find and process all makrdown validated fields."""
|
||||
for k, v in schema.items():
|
||||
if isinstance(v, dict):
|
||||
if 'validator' in v and 'markdown' == v['validator']:
|
||||
# If there is a match with the validator: markdown pair, assign the sibling
|
||||
# property (following the naming convention _<property>_html)
|
||||
# the processed value.
|
||||
if k in node:
|
||||
html = pillar.markdown.markdown(node[k])
|
||||
field_name = pillar.markdown.cache_field_name(k)
|
||||
node[field_name] = html
|
||||
if isinstance(node, dict) and k in node:
|
||||
find_markdown_fields(v, node[k])
|
||||
|
||||
find_markdown_fields(schema, node)
|
||||
|
||||
return 'ok'
|
||||
|
||||
|
||||
def parse_markdowns(items):
|
||||
for item in items:
|
||||
parse_markdown(item)
|
||||
|
||||
|
||||
def setup_app(app, url_prefix):
|
||||
from . import patch
|
||||
patch.setup_app(app, url_prefix=url_prefix)
|
||||
@@ -408,12 +443,14 @@ def setup_app(app, url_prefix):
|
||||
app.on_fetched_resource_nodes += before_returning_nodes
|
||||
|
||||
app.on_replace_nodes += before_replacing_node
|
||||
app.on_replace_nodes += parse_markdown
|
||||
app.on_replace_nodes += texture_sort_files
|
||||
app.on_replace_nodes += deduct_content_type
|
||||
app.on_replace_nodes += node_set_default_picture
|
||||
app.on_replaced_nodes += after_replacing_node
|
||||
|
||||
app.on_insert_nodes += before_inserting_nodes
|
||||
app.on_insert_nodes += parse_markdowns
|
||||
app.on_insert_nodes += nodes_deduct_content_type
|
||||
app.on_insert_nodes += nodes_set_default_picture
|
||||
app.on_insert_nodes += textures_sort_files
|
||||
|
@@ -225,4 +225,4 @@ class OrganizationPatchHandler(patch_handler.AbstractPatchHandler):
|
||||
|
||||
def setup_app(app):
|
||||
OrganizationPatchHandler(patch_api_blueprint)
|
||||
app.register_api_blueprint(patch_api_blueprint, url_prefix='/organizations')
|
||||
# app.register_api_blueprint(patch_api_blueprint, url_prefix='/organizations')
|
||||
|
@@ -522,13 +522,12 @@ class AbstractPillarTest(TestMinimal):
|
||||
expected_status, resp.status_code, resp.data
|
||||
))
|
||||
|
||||
def get_json():
|
||||
if resp.mimetype != 'application/json':
|
||||
raise TypeError('Unable to load JSON from mimetype %r' % resp.mimetype)
|
||||
return mod_json.loads(resp.data)
|
||||
|
||||
resp.json = get_json
|
||||
resp.get_json = get_json
|
||||
# def get_json():
|
||||
# if resp.mimetype != 'application/json':
|
||||
# raise TypeError('Unable to load JSON from mimetype %r' % resp.mimetype)
|
||||
# return mod_json.loads(resp.data)
|
||||
#
|
||||
# resp.get_json = get_json
|
||||
|
||||
return resp
|
||||
|
||||
@@ -561,7 +560,7 @@ class AbstractPillarTest(TestMinimal):
|
||||
raise TypeError('expected_user_id should be a string or ObjectId, '
|
||||
f'but is {expected_user_id!r}')
|
||||
|
||||
resp = self.get('/api/users/me', expected_status=200, auth_token=token).json()
|
||||
resp = self.get('/api/users/me', expected_status=200, auth_token=token).get_json()
|
||||
|
||||
if expected_user_id:
|
||||
self.assertEqual(resp['_id'], str(expected_user_id))
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
BLENDER_ID_ENDPOINT = 'http://id.local:8001' # Non existant server
|
||||
|
||||
SERVER_NAME = 'localhost'
|
||||
PILLAR_SERVER_ENDPOINT = 'http://localhost/api/'
|
||||
SERVER_NAME = 'localhost.local'
|
||||
PILLAR_SERVER_ENDPOINT = 'http://localhost.local/api/'
|
||||
|
||||
MAIN_PROJECT_ID = '5672beecc0261b2005ed1a33'
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
from pillar.api.eve_settings import *
|
||||
|
||||
MONGO_DBNAME = 'pillar_test'
|
||||
MONGO_USERNAME = None
|
||||
|
||||
|
||||
def override_eve():
|
||||
@@ -10,5 +11,7 @@ def override_eve():
|
||||
test_settings.MONGO_HOST = MONGO_HOST
|
||||
test_settings.MONGO_PORT = MONGO_PORT
|
||||
test_settings.MONGO_DBNAME = MONGO_DBNAME
|
||||
test_settings.MONGO1_USERNAME = MONGO_USERNAME
|
||||
tests.MONGO_HOST = MONGO_HOST
|
||||
tests.MONGO_DBNAME = MONGO_DBNAME
|
||||
tests.MONGO_USERNAME = MONGO_USERNAME
|
||||
|
@@ -21,7 +21,7 @@ def attachment_form_group_create(schema_prop):
|
||||
def _attachment_build_single_field(schema_prop):
|
||||
# Ugly hard-coded schema.
|
||||
fake_schema = {
|
||||
'slug': schema_prop['propertyschema'],
|
||||
'slug': schema_prop['keyschema'],
|
||||
'oid': schema_prop['valueschema']['schema']['oid'],
|
||||
}
|
||||
file_select_form_group = build_file_select_form(fake_schema)
|
||||
|
Reference in New Issue
Block a user