Introducing Cloud extension

We use a Pillar extension to register Blender Cloud specific endpoints.
This commit is contained in:
Francesco Siddi 2017-03-10 15:36:30 +01:00
parent 2f1a32178a
commit 1d687d5c01
7 changed files with 381 additions and 32 deletions

71
cloud/__init__.py Normal file
View File

@ -0,0 +1,71 @@
import logging
import flask
from werkzeug.local import LocalProxy
from pillar.extension import PillarExtension
EXTENSION_NAME = 'cloud'
class CloudExtension(PillarExtension):
def __init__(self):
self._log = logging.getLogger('%s.CloudExtension' % __name__)
@property
def name(self):
return EXTENSION_NAME
def flask_config(self):
"""Returns extension-specific defaults for the Flask configuration.
Use this to set sensible default values for configuration settings
introduced by the extension.
:rtype: dict
"""
# Just so that it registers the management commands.
from . import cli
return {}
def eve_settings(self):
"""Returns extensions to the Eve settings.
Currently only the DOMAIN key is used to insert new resources into
Eve's configuration.
:rtype: dict
"""
return {}
def blueprints(self):
"""Returns the list of top-level blueprints for the extension.
These blueprints will be mounted at the url prefix given to
app.load_extension().
:rtype: list of flask.Blueprint objects.
"""
from . import routes
return [routes.blueprint]
@property
def template_path(self):
import os.path
return os.path.join(os.path.dirname(__file__), 'templates')
@property
def static_path(self):
import os.path
return os.path.join(os.path.dirname(__file__), 'static')
def _get_current_cloud():
"""Returns the Cloud extension of the current application."""
return flask.current_app.pillar_extensions[EXTENSION_NAME]
current_cloud = LocalProxy(_get_current_cloud)
"""Cloud extension of the current app."""

40
cloud/cli.py Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env python
import logging
from flask import current_app
from flask_script import Manager
from pillar.cli import manager
log = logging.getLogger(__name__)
manager_cloud = Manager(
current_app, usage="Blender Cloud scripts")
@manager_cloud.command
def reconcile_subscribers():
"""For every user, check their subscription status with the store."""
from pillar.auth.subscriptions import fetch_user
users_coll = current_app.data.driver.db['users']
unsubscribed_users = []
for user in users_coll.find({'roles': 'subscriber'}):
print('Processing %s' % user['email'])
print(' Checking subscription')
user_store = fetch_user(user['email'])
if user_store['cloud_access'] == 0:
print(' Removing subscriber role')
users_coll.update(
{'_id': user['_id']},
{'$pull': {'roles': 'subscriber'}})
unsubscribed_users.append(user['email'])
if not unsubscribed_users:
return
print('The following users have been unsubscribed')
for user in unsubscribed_users:
print(user)
manager.add_command("cloud", manager_cloud)

11
cloud/routes.py Normal file
View File

@ -0,0 +1,11 @@
import logging
from flask import Blueprint, render_template
blueprint = Blueprint('cloud', __name__)
log = logging.getLogger(__name__)
@blueprint.route('/about')
def about():
return render_template('about.html')

252
cloud/templates/about.html Normal file
View File

@ -0,0 +1,252 @@
{% extends 'layout.html' %}
{% block page_title %}Welcome{% endblock %}
{% block body %}
<div id="page-container">
<div id="page-header">
<div style="text-align: left" class="page-title">
<em>ABOUT</em>
<i class="pi-blender-cloud-logo"></i>
</div>
<div class="page-title-summary">
Blender Cloud means inspiration, knowledge, and tools in one place.<br>Started in 2015, it has been pushing the meaning of recurring crowdfunding ever since.<br> By subscribing to Blender Cloud you support the creation of open content, the development of high-end production tools like Blender and access a unique set of learning and creative resources.
</div>
</div>
<div id="page-content">
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Launch at SXSW <small>March 9th, 2014</small>
</h2>
<div class="page-card-summary">
First happy cloud video and crowdfunding for Cosmos Laundromat Pilot.
</div>
</div>
<div class="page-card-side">
<a href="https://gooseberry.blender.org/gooseberry-campaign-launched-we-need-10k-people-to-help/"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://gooseberry.blender.org/gooseberry-campaign-launched-we-need-10k-people-to-help/"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Gooseberry | Cosmos Laundromat <small>March 10th, 2015</small>
</h2>
<div class="page-card-summary">
Weekly folders with updates for subscribers. Initial development of Attract, which will become the new cloud some months later on.
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Glass Half <small>October 30th, 2015</small>
</h2>
<div class="page-card-summary">
Introducing integrated blogs in Blender Cloud projects. Glass Half is the first project fully developed on the new Blender Cloud. It&#39;s also the first and only project to have share its <a href="https://cloud.blender.org/p/glass-half/5627bb22f0e7220061109c9f">animation dailies</a>! But the biggest outcome from Glass Half was definitely <a href="https://cloud.blender.org/p/glass-half/569d6044c379cf445461293e">Flexirig</a>.
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/p/glass-half/blog/glass-half-premiere"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/new-art-gallery-with-gleb-alexandrov"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Art Gallery <small>November 19th, 2015</small>
</h2>
<div class="page-card-summary">
Learn by example. Introducing a place for amazing artwork to be shared, along with its blendfiles and breakdowns.
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Blender Institute Podcast <small>November 24th, 2015</small>
</h2>
<div class="page-card-summary">
With so much going on in the Cloud at at the studio. The Blender Institute Podcast was born! Sharing our daily studio work, Blender community news, and interacting with the awesome Blender Cloud subscribers.
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-blender-institute-podcast"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/p/blenrig/blog/welcome-to-the-blenrig-project"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Blenrig <small>December 1st, 2015</small>
</h2>
<div class="page-card-summary">
The most powerful and versatile rigging framework for Blender, used and tested through Cosmos Laundromat and the Caminandes series, is now part of Blender Cloud!
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Texture Library <small>December 23rd, 2015</small>
</h2>
<div class="page-card-summary">
The biggest source for CC0/Public Domain textures on the interwebs goes live. First as beta, as a quick gift right before Xmas 2015!
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/new-texture-library"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/nraryew-the-character-lib"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Character Library <small>January 5th, 2016</small>
</h2>
<div class="page-card-summary">
High-quality, animation-ready characters collection from all the Blender Institute open projects, plus a brand new one: Vincent!
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Caminandes: Llamigos <small>January 30th, 2016</small>
</h2>
<div class="page-card-summary">
The <a href="https://www.youtube.com/watch?v=SkVqJ1SGeL0">third episode</a> of the Caminandes series was completely done -and sponsored! through Blender Cloud. It&#39;s also the only project til date to have <a href="https://www.youtube.com/watch?v=kQH897V9bDg&amp;list=PLI2TkLMzCSr_H6ppmzDtU0ut0RwxGvXjv">nicely edited Weekly video reports</a>.
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/p/caminandes-3/blog/caminandes-llamigos"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/welcome-sybren"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Sybren <small>March 1st, 2016</small>
</h2>
<div class="page-card-summary">
Dr. Sybren Stüvel starts working at the Blender Institute!
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Private Projects <small>May 3rd, 2016</small>
</h2>
<div class="page-card-summary">
Create your own private projects on Blender Cloud.
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/welcome-sybren"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-project-sharing"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Project Sharing <small>May 9th, 2016</small>
</h2>
<div class="page-card-summary">
Team work! Share your projects with other Blender Cloud subscribers.
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Blender Cloud add-on with Texture Library <small>May 11th, 2016</small>
</h2>
<div class="page-card-summary">
Browse the textures from within Blender!
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-project-sharing"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-private-texture-libraries"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Private Texture Libraries <small>May 23rd, 2016</small>
</h2>
<div class="page-card-summary">
Create your own private textures library and browse it in Blender with our add-on.
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
Blender Sync <small>June 30th, 2016</small>
</h2>
<div class="page-card-summary">
Sync your Blender preferences across multiple devices.
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-blender-sync"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-image-sharing"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
Image Sharing <small>July 14th, 2016</small>
</h2>
<div class="page-card-summary">
Quickly share renders and Blender screenshots within Blender with our add-on.
</div>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<h2 class="page-card-title">
<a href="https://cloud.blender.org/blog/introducing-the-hdri-library">HDRI Library <small>July 27th, 2016</small></a>
</h2>
<div class="page-card-summary">
High-dynamic range images are now available on Blender Cloud! With their own special viewer. Also available via the Blender Cloud add-on.
</div>
</div>
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-the-hdri-library"><img src="https://placehold.it/400x200"></a>
</div>
</section>
<section class="page-card">
<div class="page-card-side">
<a href="https://cloud.blender.org/blog/introducing-the-hdri-library"><img src="https://placehold.it/400x200"></a>
</div>
<div class="page-card-side">
<h2 class="page-card-title">
<a href="https://cloud.blender.org/blog/new-training-toon-character-workflow">Toon Character Workflow <small>December 6th, 2016</small></a>
</h2>
<div class="page-card-summary">
YouTube star Dillon Gu joins Blender Cloud for a new tutorial series that will guide you from the basics to a finished toon-shaded character.
</div>
</div>
</section>
</div>
</div>
{% endblock body%}

View File

@ -1,38 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import logging
from flask import current_app
from pillar import cli from pillar import cli
from pillar.cli import manager_maintenance from runserver import app
from cloud import app
log = logging.getLogger(__name__)
@manager_maintenance.command
def reconcile_subscribers():
"""For every user, check their subscription status with the store."""
from pillar.auth.subscriptions import fetch_user
users_coll = current_app.data.driver.db['users']
unsubscribed_users = []
for user in users_coll.find({'roles': 'subscriber'}):
print('Processing %s' % user['email'])
print(' Checking subscription')
user_store = fetch_user(user['email'])
if user_store['cloud_access'] == 0:
print(' Removing subscriber role')
users_coll.update(
{'_id': user['_id']},
{'$pull': {'roles': 'subscriber'}})
unsubscribed_users.append(user['email'])
if not unsubscribed_users:
return
print('The following users have been unsubscribed')
for user in unsubscribed_users:
print(user)
cli.manager.app = app cli.manager.app = app
cli.manager.run() cli.manager.run()

View File

@ -3,13 +3,16 @@
from pillar import PillarServer from pillar import PillarServer
from attract import AttractExtension from attract import AttractExtension
from flamenco import FlamencoExtension from flamenco import FlamencoExtension
from cloud import CloudExtension
attract = AttractExtension() attract = AttractExtension()
flamenco = FlamencoExtension() flamenco = FlamencoExtension()
cloud = CloudExtension()
app = PillarServer('.') app = PillarServer('.')
app.load_extension(attract, '/attract') app.load_extension(attract, '/attract')
app.load_extension(flamenco, '/flamenco') app.load_extension(flamenco, '/flamenco')
app.load_extension(cloud, None)
app.process_extensions() app.process_extensions()
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -4,13 +4,16 @@ import sys
from pillar import PillarServer from pillar import PillarServer
from attract import AttractExtension from attract import AttractExtension
from flamenco import FlamencoExtension from flamenco import FlamencoExtension
from cloud import CloudExtension
sys.path.append('/data/git/blender-cloud') sys.path.append('/data/git/blender-cloud')
attract = AttractExtension() attract = AttractExtension()
flamenco = FlamencoExtension() flamenco = FlamencoExtension()
cloud = CloudExtension()
application = PillarServer(dirname(abspath(__file__))) application = PillarServer(dirname(abspath(__file__)))
application.load_extension(attract, '/attract') application.load_extension(attract, '/attract')
application.load_extension(flamenco, '/flamenco') application.load_extension(flamenco, '/flamenco')
application.load_extension(cloud, None)
application.process_extensions() application.process_extensions()