Include HDRi projects in /bcloud/texture-libraries
This depends on the version of the Blender Cloud Addon, which will be sent as Blender-Cloud-Addon HTTP header in a future version of the addon.
This commit is contained in:
parent
d34d129a2f
commit
4a72b377bd
@ -1,3 +1,27 @@
|
|||||||
|
from flask import request
|
||||||
|
from werkzeug import exceptions as wz_exceptions
|
||||||
|
|
||||||
|
|
||||||
|
def blender_cloud_addon_version():
|
||||||
|
"""Returns the version of the Blender Cloud Addon, or None if not given in the request.
|
||||||
|
|
||||||
|
Uses the 'Blender-Cloud-Addon' HTTP header.
|
||||||
|
|
||||||
|
:returns: the version of the addon, as tuple (major, minor, micro)
|
||||||
|
:rtype: tuple or None
|
||||||
|
:raises: werkzeug.exceptions.BadRequest if the header is malformed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
header = request.headers.get('Blender-Cloud-Addon')
|
||||||
|
if not header:
|
||||||
|
return None
|
||||||
|
|
||||||
|
parts = header.split('.')
|
||||||
|
try:
|
||||||
|
return tuple(int(part) for part in parts)
|
||||||
|
except ValueError:
|
||||||
|
raise wz_exceptions.BadRequest('Invalid Blender-Cloud-Addon header')
|
||||||
|
|
||||||
|
|
||||||
def setup_app(app, url_prefix):
|
def setup_app(app, url_prefix):
|
||||||
from . import texture_libs, home_project
|
from . import texture_libs, home_project
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import functools
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from flask import Blueprint, request, current_app, g
|
from flask import Blueprint, request, current_app, g
|
||||||
@ -9,6 +10,7 @@ from werkzeug.exceptions import InternalServerError
|
|||||||
from application import utils
|
from application import utils
|
||||||
from application.utils.authorization import require_login
|
from application.utils.authorization import require_login
|
||||||
|
|
||||||
|
FIRST_ADDON_VERSION_WITH_HDRI = (1, 4, 0)
|
||||||
TL_PROJECTION = utils.dumps({'name': 1, 'url': 1, 'permissions': 1,})
|
TL_PROJECTION = utils.dumps({'name': 1, 'url': 1, 'permissions': 1,})
|
||||||
TL_SORT = utils.dumps([('name', 1)])
|
TL_SORT = utils.dumps([('name', 1)])
|
||||||
|
|
||||||
@ -60,15 +62,22 @@ def keep_fetching_texture_libraries(proj_filter):
|
|||||||
@blueprint.route('/texture-libraries')
|
@blueprint.route('/texture-libraries')
|
||||||
@require_login()
|
@require_login()
|
||||||
def texture_libraries():
|
def texture_libraries():
|
||||||
|
from . import blender_cloud_addon_version
|
||||||
|
|
||||||
# Use Eve method so that we get filtering on permissions for free.
|
# Use Eve method so that we get filtering on permissions for free.
|
||||||
# This gives all the projects that contain the required node types.
|
# This gives all the projects that contain the required node types.
|
||||||
|
|
||||||
request.args = MultiDict(request.args) # allow changes; it's an ImmutableMultiDict by default.
|
request.args = MultiDict(request.args) # allow changes; it's an ImmutableMultiDict by default.
|
||||||
request.args.setlist(eve_config.QUERY_PROJECTION, [TL_PROJECTION])
|
request.args.setlist(eve_config.QUERY_PROJECTION, [TL_PROJECTION])
|
||||||
request.args.setlist(eve_config.QUERY_SORT, [TL_SORT])
|
request.args.setlist(eve_config.QUERY_SORT, [TL_SORT])
|
||||||
|
|
||||||
|
# Determine whether to return HDRi projects too, based on the version
|
||||||
|
# of the Blender Cloud Addon. If the addon version is None, we're dealing
|
||||||
|
# with a version of the BCA that's so old it doesn't send its version along.
|
||||||
|
return_hdri = blender_cloud_addon_version() > FIRST_ADDON_VERSION_WITH_HDRI
|
||||||
|
accept_as_library = functools.partial(has_texture_node, return_hdri=return_hdri)
|
||||||
|
|
||||||
# Construct eve-like response.
|
# Construct eve-like response.
|
||||||
projects = list(keep_fetching_texture_libraries(has_texture_node))
|
projects = list(keep_fetching_texture_libraries(accept_as_library))
|
||||||
result = {'_items': projects,
|
result = {'_items': projects,
|
||||||
'_meta': {
|
'_meta': {
|
||||||
'max_results': len(projects),
|
'max_results': len(projects),
|
||||||
@ -79,13 +88,18 @@ def texture_libraries():
|
|||||||
return utils.jsonify(result)
|
return utils.jsonify(result)
|
||||||
|
|
||||||
|
|
||||||
def has_texture_node(proj):
|
def has_texture_node(proj, return_hdri=True):
|
||||||
"""Returns True iff the project has a top-level (group)texture node."""
|
"""Returns True iff the project has a top-level (group)texture node."""
|
||||||
|
|
||||||
nodes_collection = current_app.data.driver.db['nodes']
|
nodes_collection = current_app.data.driver.db['nodes']
|
||||||
|
|
||||||
|
# See which types of nodes we support.
|
||||||
|
node_types = ['group_texture']
|
||||||
|
if return_hdri:
|
||||||
|
node_types.append('hdri')
|
||||||
|
|
||||||
count = nodes_collection.count(
|
count = nodes_collection.count(
|
||||||
{'node_type': 'group_texture',
|
{'node_type': {'$in': node_types},
|
||||||
'project': proj['_id'],
|
'project': proj['_id'],
|
||||||
'parent': None})
|
'parent': None})
|
||||||
return count > 0
|
return count > 0
|
||||||
|
@ -8,13 +8,14 @@ import logging
|
|||||||
import responses
|
import responses
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
|
from werkzeug import exceptions as wz_exceptions
|
||||||
|
|
||||||
from common_test_class import AbstractPillarTest, TEST_EMAIL_ADDRESS
|
from common_test_class import AbstractPillarTest, TEST_EMAIL_ADDRESS
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HomeProjectTest(AbstractPillarTest):
|
class AbstractHomeProjectTest(AbstractPillarTest):
|
||||||
def setUp(self, **kwargs):
|
def setUp(self, **kwargs):
|
||||||
AbstractPillarTest.setUp(self, **kwargs)
|
AbstractPillarTest.setUp(self, **kwargs)
|
||||||
self.create_standard_groups()
|
self.create_standard_groups()
|
||||||
@ -28,6 +29,8 @@ class HomeProjectTest(AbstractPillarTest):
|
|||||||
self.create_valid_auth_token(user_id, token)
|
self.create_valid_auth_token(user_id, token)
|
||||||
return user_id
|
return user_id
|
||||||
|
|
||||||
|
|
||||||
|
class HomeProjectTest(AbstractHomeProjectTest):
|
||||||
def test_create_home_project(self):
|
def test_create_home_project(self):
|
||||||
from application.modules.blender_cloud import home_project
|
from application.modules.blender_cloud import home_project
|
||||||
from application.utils.authentication import validate_token
|
from application.utils.authentication import validate_token
|
||||||
@ -421,3 +424,87 @@ class HomeProjectUserChangedRoleTest(AbstractPillarTest):
|
|||||||
headers={'Authorization': self.make_header('token'),
|
headers={'Authorization': self.make_header('token'),
|
||||||
'Content-Type': 'application/json'})
|
'Content-Type': 'application/json'})
|
||||||
self.assertEqual(status_code, resp.status_code, resp.data)
|
self.assertEqual(status_code, resp.status_code, resp.data)
|
||||||
|
|
||||||
|
|
||||||
|
class TextureLibraryTest(AbstractHomeProjectTest):
|
||||||
|
def create_node(self, node_doc):
|
||||||
|
with self.app.test_request_context():
|
||||||
|
nodes_coll = self.app.data.driver.db['nodes']
|
||||||
|
result = nodes_coll.insert_one(node_doc)
|
||||||
|
return result.inserted_id
|
||||||
|
|
||||||
|
def setUp(self, **kwargs):
|
||||||
|
AbstractHomeProjectTest.setUp(self, **kwargs)
|
||||||
|
|
||||||
|
user_id = self._create_user_with_token(set(), 'token')
|
||||||
|
self.hdri_proj_id, proj = self.ensure_project_exists(project_overrides={'_id': 24 * 'a'})
|
||||||
|
self.tex_proj_id, proj2 = self.ensure_project_exists(project_overrides={'_id': 24 * 'b'})
|
||||||
|
|
||||||
|
self.create_node({'description': '',
|
||||||
|
'project': self.hdri_proj_id,
|
||||||
|
'node_type': 'hdri',
|
||||||
|
'user': user_id,
|
||||||
|
'properties': {'status': 'published',
|
||||||
|
'tags': [],
|
||||||
|
'order': 0,
|
||||||
|
'categories': '',
|
||||||
|
'files': ''},
|
||||||
|
'name': 'HDRi test node'}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.create_node({'description': '',
|
||||||
|
'project': self.tex_proj_id,
|
||||||
|
'node_type': 'group_texture',
|
||||||
|
'user': user_id,
|
||||||
|
'properties': {'status': 'published',
|
||||||
|
'tags': [],
|
||||||
|
'order': 0,
|
||||||
|
'categories': '',
|
||||||
|
'files': ''},
|
||||||
|
'name': 'Group texture test node'}
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_blender_cloud_addon_version(self):
|
||||||
|
from application.modules.blender_cloud import blender_cloud_addon_version
|
||||||
|
|
||||||
|
# Three-digit version
|
||||||
|
with self.app.test_request_context(headers={'Blender-Cloud-Addon': '1.3.3'}):
|
||||||
|
self.assertEqual((1, 3, 3), blender_cloud_addon_version())
|
||||||
|
|
||||||
|
# Two-digit version
|
||||||
|
with self.app.test_request_context(headers={'Blender-Cloud-Addon': '1.5'}):
|
||||||
|
self.assertEqual((1, 5), blender_cloud_addon_version())
|
||||||
|
|
||||||
|
# No version
|
||||||
|
with self.app.test_request_context():
|
||||||
|
self.assertEqual(None, blender_cloud_addon_version())
|
||||||
|
|
||||||
|
# Malformed version
|
||||||
|
with self.app.test_request_context(headers={'Blender-Cloud-Addon': 'je moeder'}):
|
||||||
|
self.assertRaises(wz_exceptions.BadRequest, blender_cloud_addon_version)
|
||||||
|
|
||||||
|
def test_hdri_library__no_bcloud_version(self):
|
||||||
|
resp = self.get('/bcloud/texture-libraries', auth_token='token')
|
||||||
|
libs = resp.json()['_items']
|
||||||
|
library_project_ids = {proj['_id'] for proj in libs}
|
||||||
|
|
||||||
|
self.assertNotIn(unicode(self.hdri_proj_id), library_project_ids)
|
||||||
|
self.assertIn(unicode(self.tex_proj_id), library_project_ids)
|
||||||
|
|
||||||
|
def test_hdri_library__old_bcloud_addon(self):
|
||||||
|
resp = self.get('/bcloud/texture-libraries',
|
||||||
|
auth_token='token',
|
||||||
|
headers={'Blender-Cloud-Addon': '1.3.3'})
|
||||||
|
libs = resp.json()['_items']
|
||||||
|
library_project_ids = {proj['_id'] for proj in libs}
|
||||||
|
self.assertNotIn(unicode(self.hdri_proj_id), library_project_ids)
|
||||||
|
self.assertIn(unicode(self.tex_proj_id), library_project_ids)
|
||||||
|
|
||||||
|
def test_hdri_library__new_bcloud_addon(self):
|
||||||
|
resp = self.get('/bcloud/texture-libraries',
|
||||||
|
auth_token='token',
|
||||||
|
headers={'Blender-Cloud-Addon': '1.4.0'})
|
||||||
|
libs = resp.json()['_items']
|
||||||
|
library_project_ids = {proj['_id'] for proj in libs}
|
||||||
|
self.assertNotIn(unicode(self.hdri_proj_id), library_project_ids)
|
||||||
|
self.assertIn(unicode(self.tex_proj_id), library_project_ids)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user