WIP on libraries upgrade

This commit is contained in:
2018-07-12 15:23:57 +02:00
parent 49075cbc60
commit 549cf0a3e8
29 changed files with 177 additions and 148 deletions

View File

@@ -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):

View File

@@ -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'},
}
}

View File

@@ -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']

View File

@@ -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,
},

View File

@@ -7,7 +7,7 @@ node_type_comment = {
'type': 'string',
'minlength': 5,
'required': True,
'coerce': 'markdown',
'validator': 'markdown',
},
'_content_html': {'type': 'string'},
'status': {

View File

@@ -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},

View File

@@ -9,7 +9,7 @@ node_type_post = {
'minlength': 5,
'maxlength': 90000,
'required': True,
'coerce': 'markdown',
'validator': 'markdown',
},
'_content_html': {'type': 'string'},
'status': {

View File

@@ -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

View File

@@ -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')

View File

@@ -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))

View File

@@ -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'

View File

@@ -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

View File

@@ -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)