Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving to Python3 #247

Merged
merged 4 commits into from
Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
language: python
python:
- "2.7"
- "3.6"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump to 3.7

# command to install dependencies
install:
- npm i npm@latest -g
Expand Down
14 changes: 7 additions & 7 deletions hgtv/forms/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@


class ChannelForm(forms.Form):
type = forms.SelectField(u"Channel type", coerce=int, validators=[forms.validators.DataRequired()])
description = forms.TinyMce4Field(u"Description")
bio = forms.StringField(u"Bio",
description=u"This text is the short description of the channel shown on the homepage")
channel_logo = forms.FileField(u"Channel logo",
type = forms.SelectField("Channel type", coerce=int, validators=[forms.validators.DataRequired()])
description = forms.TinyMce4Field("Description")
bio = forms.StringField("Bio",
description="This text is the short description of the channel shown on the homepage")
channel_logo = forms.FileField("Channel logo",
description="Optional - Channel logos are shown on the homepage when the channel is featured")
channel_banner_url = forms.URLField(u"Channel banner image url")
delete_logo = forms.BooleanField(u"Remove existing logo?")
channel_banner_url = forms.URLField("Channel banner image url")
delete_logo = forms.BooleanField("Remove existing logo?")
34 changes: 17 additions & 17 deletions hgtv/forms/playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@


class PlaylistForm(forms.Form):
title = forms.StringField(u"Title", validators=[forms.validators.DataRequired()],
description=u"The name of your playlist")
name = forms.StringField(u"URL Name",
description=u"Optional. Will be automatically generated if left blank")
description = forms.TinyMce4Field(u"Description")
recorded_date = forms.DateField(u"Recorded date",
description=u"Date on which the videos in this playlist were recorded, if applicable")
published_date = forms.DateField(u"Published date", validators=[forms.validators.DataRequired()],
description=u"Date on which this playlist was created or made public")
public = forms.BooleanField(u"This playlist is public", default=True)
banner_image = forms.FileField(u"Playlist banner ad", description="Optional - Ad will be displayed in playlist page")
banner_ad_url = forms.URLField(u"Banner Ad URL", description="URL to which user should be redirected to")
delete_banner_ad = forms.BooleanField(u"Delete existing ad?")
title = forms.StringField("Title", validators=[forms.validators.DataRequired()],
description="The name of your playlist")
name = forms.StringField("URL Name",
description="Optional. Will be automatically generated if left blank")
description = forms.TinyMce4Field("Description")
recorded_date = forms.DateField("Recorded date",
description="Date on which the videos in this playlist were recorded, if applicable")
published_date = forms.DateField("Published date", validators=[forms.validators.DataRequired()],
description="Date on which this playlist was created or made public")
public = forms.BooleanField("This playlist is public", default=True)
banner_image = forms.FileField("Playlist banner ad", description="Optional - Ad will be displayed in playlist page")
banner_ad_url = forms.URLField("Banner Ad URL", description="URL to which user should be redirected to")
delete_banner_ad = forms.BooleanField("Delete existing ad?")

def validate_name(self, field):
if invalid_name.search(field.data):
Expand All @@ -42,12 +42,12 @@ def validate_banner_ad(self, field):
if field.data and 'banner_ad' in request.files:
requestfile = request.files['banner_ad']
fileext = requestfile.filename.split('.')[-1].lower()
if fileext not in [u'png', u'jpg', u'jpeg']:
raise UploadNotAllowed(u"Unsupported file format. Only PNG and JPG are supported")
if fileext not in ['png', 'jpg', 'jpeg']:
raise UploadNotAllowed("Unsupported file format. Only PNG and JPG are supported")
img = Image.open(requestfile)
img.load()
if not img.size == BANNER_AD_ALLOWED_SIZE:
raise UploadNotAllowed(u"Banner size should be %sx%s" % (BANNER_AD_ALLOWED_SIZE[0], BANNER_AD_ALLOWED_SIZE[1]))
raise UploadNotAllowed("Banner size should be %sx%s" % (BANNER_AD_ALLOWED_SIZE[0], BANNER_AD_ALLOWED_SIZE[1]))


class PlaylistAddForm(forms.Form):
Expand All @@ -60,4 +60,4 @@ def playlist_validate_url(self, field):


class PlaylistImportForm(forms.Form):
playlist_url = forms.URLField(u"Playlist URL", validators=[forms.validators.DataRequired(), playlist_validate_url])
playlist_url = forms.URLField("Playlist URL", validators=[forms.validators.DataRequired(), playlist_validate_url])
22 changes: 11 additions & 11 deletions hgtv/forms/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@


class VideoAddForm(forms.Form):
video_url = forms.URLField(u"Video URL", validators=[forms.validators.DataRequired()])
slides_url = forms.URLField(u"Slides URL")
video_url = forms.URLField("Video URL", validators=[forms.validators.DataRequired()])
slides_url = forms.URLField("Slides URL")


class VideoEditForm(forms.Form):
title = forms.StringField(u"Title", validators=[forms.validators.DataRequired()],
description=u"Video title, without the speakers’ names")
description = forms.TinyMce4Field(u'Description', description=u"Summary of this video's content")
speakers = forms.UserSelectMultiField(u"Speakers",
description=u"Lookup a user by their username or email address", usermodel=User, lastuser=lastuser)
video_url = forms.URLField(u"Video URL", validators=[forms.validators.DataRequired()])
slides_url = forms.URLField(u"Slides URL")
video_slides_mapping = forms.TextAreaField(u"Video slides mapping",
description=u'Mapping of Video timing in seconds and slide number. E.g {"0": 1, "10": 2}')
title = forms.StringField("Title", validators=[forms.validators.DataRequired()],
description="Video title, without the speakers’ names")
description = forms.TinyMce4Field('Description', description="Summary of this video's content")
speakers = forms.UserSelectMultiField("Speakers",
description="Lookup a user by their username or email address", usermodel=User, lastuser=lastuser)
video_url = forms.URLField("Video URL", validators=[forms.validators.DataRequired()])
slides_url = forms.URLField("Slides URL")
video_slides_mapping = forms.TextAreaField("Video slides mapping",
description='Mapping of Video timing in seconds and slide number. E.g {"0": 1, "10": 2}')


class VideoActionForm(forms.Form):
Expand Down
20 changes: 10 additions & 10 deletions hgtv/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@


class PLAYLIST_AUTO_TYPE(LabeledEnum):
WATCHED = (1, u'watched', __(u"Watched"))
STARRED = (2, u'starred', __(u"Starred"))
LIKED = (3, u'liked', __(u"Liked"))
DISLIKED = (4, u'disliked', __(u"Disliked"))
SPEAKING_IN = (5, u'speaking-in', __(u"Speaking in"))
APPEARING_IN = (6, u'appearing-in', __(u"Appearing in"))
CREW_IN = (7, u'crew-in', __(u"Crew in"))
ATTENDED = (8, u'attended', __(u"Attended"))
QUEUE = (9, u'queue', __(u"Queue"))
STREAM = (10, u'stream', __(u"All videos"))
WATCHED = (1, 'watched', __("Watched"))
STARRED = (2, 'starred', __("Starred"))
LIKED = (3, 'liked', __("Liked"))
DISLIKED = (4, 'disliked', __("Disliked"))
SPEAKING_IN = (5, 'speaking-in', __("Speaking in"))
APPEARING_IN = (6, 'appearing-in', __("Appearing in"))
CREW_IN = (7, 'crew-in', __("Crew in"))
ATTENDED = (8, 'attended', __("Attended"))
QUEUE = (9, 'queue', __("Queue"))
STREAM = (10, 'stream', __("All videos"))


from hgtv.models.video import *
Expand Down
26 changes: 13 additions & 13 deletions hgtv/models/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,26 @@


class CHANNEL_TYPE(LabeledEnum):
UNDEFINED = (0, u"Channel")
PERSON = (1, u"Person")
ORGANIZATION = (2, u"Organization")
EVENTSERIES = (3, u"Event Series")
UNDEFINED = (0, "Channel")
PERSON = (1, "Person")
ORGANIZATION = (2, "Organization")
EVENTSERIES = (3, "Event Series")

__order__ = (UNDEFINED, PERSON, ORGANIZATION, EVENTSERIES)


class PLAYLIST_TYPE(LabeledEnum):
REGULAR = (0, u"Playlist")
EVENT = (1, u"Event")
REGULAR = (0, "Playlist")
EVENT = (1, "Event")


class Channel(ProfileBase, db.Model):
__tablename__ = 'channel'
description = db.Column(db.UnicodeText, default=u'', nullable=False)
description = db.Column(db.UnicodeText, default='', nullable=False)
bio = db.Column(db.Unicode(250), nullable=True)
featured = db.Column(db.Boolean, default=False, nullable=False)
type = db.Column(db.Integer, default=CHANNEL_TYPE.UNDEFINED, nullable=False)
channel_logo_filename = db.Column(db.Unicode(250), nullable=True, default=u'')
channel_logo_filename = db.Column(db.Unicode(250), nullable=True, default='')
channel_banner_url = db.Column(db.Unicode(250), nullable=True)

__roles__ = {
Expand Down Expand Up @@ -97,8 +97,8 @@ def get_auto_playlist(self, auto_type, create=False, public=False):
if playlist is None and create:
playlist = Playlist(channel=self,
auto_type=auto_type,
name=unicode(PLAYLIST_AUTO_TYPE[auto_type].name),
title=unicode(PLAYLIST_AUTO_TYPE[auto_type].title),
name=PLAYLIST_AUTO_TYPE[auto_type].name,
title=PLAYLIST_AUTO_TYPE[auto_type].title,
public=public) # Automatic playlists are hidden by default
db.session.add(playlist)
return playlist
Expand Down Expand Up @@ -175,15 +175,15 @@ def url_for(self, action='view', _external=False):
class Playlist(BaseScopedNameMixin, db.Model):
__tablename__ = 'playlist'
channel_id = db.Column(db.Integer, db.ForeignKey('channel.id'), nullable=False)
description = db.Column(db.UnicodeText, default=u'', nullable=False)
description = db.Column(db.UnicodeText, default='', nullable=False)
public = db.Column(db.Boolean, nullable=False, default=True)
recorded_date = db.Column(db.Date, nullable=True)
published_date = db.Column(db.Date, nullable=False, default=date.today)
featured = db.Column(db.Boolean, default=False, nullable=False)
type = db.Column(db.Integer, default=PLAYLIST_TYPE.REGULAR, nullable=False)
auto_type = db.Column(db.Integer, nullable=True)
banner_ad_filename = db.Column(db.Unicode(250), nullable=True, default=u'')
banner_ad_url = db.Column(db.Unicode(250), nullable=True, default=u'')
banner_ad_filename = db.Column(db.Unicode(250), nullable=True, default='')
banner_ad_url = db.Column(db.Unicode(250), nullable=True, default='')
channel = db.relationship(Channel, primaryjoin=channel_id == Channel.id,
backref=db.backref('playlists', order_by=(recorded_date.desc(), published_date.desc()),
cascade='all, delete-orphan'))
Expand Down
2 changes: 1 addition & 1 deletion hgtv/models/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def get(cls, title):
def rename(self, title):
name = make_name(title)
if self.query.filter_by(name=name).first() is not None:
raise ValueError(u"Name already in use")
raise ValueError("Name already in use")
else:
self.name = name
self.title = title
Expand Down
40 changes: 20 additions & 20 deletions hgtv/models/video.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

import urllib
import urllib.request, urllib.parse, urllib.error
from sqlalchemy.ext.associationproxy import association_proxy
from werkzeug import cached_property
from flask import Markup, url_for, current_app
Expand All @@ -25,18 +25,18 @@ class Video(BaseIdNameMixin, db.Model):
playlist = db.relationship('Playlist',
backref=db.backref('primary_videos', cascade='all, delete-orphan'))
channel = association_proxy('playlist', 'channel')
description = db.Column(db.UnicodeText, nullable=False, default=u'')
description = db.Column(db.UnicodeText, nullable=False, default='')
video_url = db.Column(db.Unicode(250), nullable=False)
slides_url = db.Column(db.Unicode(250), nullable=False, default=u'')
thumbnail_path = db.Column(db.Unicode(250), nullable=True, default=u'')
slides_url = db.Column(db.Unicode(250), nullable=False, default='')
thumbnail_path = db.Column(db.Unicode(250), nullable=True, default='')

video_source = db.Column(db.Unicode(80), nullable=False, default=u'')
video_sourceid = db.Column(db.Unicode(80), nullable=False, default=u'')
video_source = db.Column(db.Unicode(80), nullable=False, default='')
video_sourceid = db.Column(db.Unicode(80), nullable=False, default='')

slides_source = db.Column(db.Unicode(80), nullable=False, default=u'')
slides_sourceid = db.Column(db.Unicode(80), nullable=False, default=u'')
video_slides_mapping = db.Column(db.UnicodeText, nullable=True, default=u'')
video_slides_mapping_json = db.Column(db.UnicodeText, nullable=True, default=u'')
slides_source = db.Column(db.Unicode(80), nullable=False, default='')
slides_sourceid = db.Column(db.Unicode(80), nullable=False, default='')
video_slides_mapping = db.Column(db.UnicodeText, nullable=True, default='')
video_slides_mapping_json = db.Column(db.UnicodeText, nullable=True, default='')

playlists = association_proxy('_playlists', 'playlist', creator=lambda x: PlaylistVideo(playlist=x))

Expand All @@ -61,7 +61,7 @@ class Video(BaseIdNameMixin, db.Model):
}

def __repr__(self):
return u'<Video %s>' % self.url_name
return '<Video %s>' % self.url_name

# ====================
# RoleMixin properties
Expand Down Expand Up @@ -190,28 +190,28 @@ def url_for(self, action='view', channel=None, playlist=None, _external=False):
video=self.url_name, _external=_external)

def embed_video_for(self, action='view'):
if self.video_source == u'youtube':
if self.video_source == 'youtube':
if action == 'edit':
return Markup('<iframe id="youtube_player" src="//www.youtube.com/embed/%s?wmode=transparent&showinfo=0&rel=0&autohide=0&autoplay=0&enablejsapi=1&version=3" frameborder="0" allowfullscreen></iframe>' % self.video_sourceid)
elif action == 'view':
return Markup('<iframe id="youtube_player" src="//videoken.com/embed/?videoID=%s&wmode=transparent&showinfo=0&rel=0&autohide=0&autoplay=1&enablejsapi=1&version=3" frameborder="0" allowfullscreen></iframe>' % self.video_sourceid)
elif self.video_source == u"vimeo":
elif self.video_source == "vimeo":
if action == 'edit':
return Markup('<iframe id="vimeo_player" src="//player.vimeo.com/video/%s?api=1&player_id=vimeoplayer" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>' % self.video_sourceid)
elif action == 'view':
return Markup('<iframe id="vimeo_player" src="//player.vimeo.com/video/%s?api=1&autoplay=1" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>' % self.video_sourceid)
elif self.video_source == u"ustream":
elif self.video_source == "ustream":
if action == 'edit':
return Markup('<iframe id="ustream_player" src="//www.ustream.tv/embed/%s?v=3&amp;wmode=direct" scrolling="no" frameborder="0" style="border: 0px none transparent;"> </iframe>' % self.video_sourceid)
elif action == 'view':
return Markup('<iframe id="ustream_player" src="//www.ustream.tv/embed/%s?v=3&amp;wmode=direct" scrolling="no" frameborder="0" style="border: 0px none transparent;"> </iframe>' % self.video_sourceid)
return u''
return ''

def embed_slides_for(self, action=None):
if self.slides_source == u'speakerdeck':
html = '<iframe src="//www.speakerdeck.com/embed/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % urllib.quote(self.slides_sourceid)
if self.slides_source == 'speakerdeck':
html = '<iframe src="//www.speakerdeck.com/embed/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % urllib.parse.quote(self.slides_sourceid)
return Markup(html)
elif self.slides_source == u'slideshare':
html = '<iframe id="slideshare" src="//www.slideshare.net/slideshow/embed_code/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % urllib.quote(self.slides_sourceid)
elif self.slides_source == 'slideshare':
html = '<iframe id="slideshare" src="//www.slideshare.net/slideshow/embed_code/%s" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>' % urllib.parse.quote(self.slides_sourceid)
return Markup(html)
return u''
return ''
21 changes: 10 additions & 11 deletions hgtv/uploads.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from PIL import Image
import os
from werkzeug import FileStorage, secure_filename
from StringIO import StringIO
from io import BytesIO
from flask import current_app
from flask_uploads import (UploadSet, configure_uploads,
IMAGES, UploadNotAllowed)
Expand All @@ -25,17 +25,16 @@ def return_werkzeug_filestorage(request, filename):
if extension not in current_app.config['ALLOWED_EXTENSIONS']:
raise UploadNotAllowed("Unsupported file format")
new_filename = secure_filename(filename + '.' + extension)
try:
tempfile = StringIO(buf=request.content)
except AttributeError:
if hasattr(request.stream, 'getvalue'):
tempfile = StringIO(buf=request.stream.getvalue())
elif hasattr(request.stream, 'read'):
tempfile = StringIO(buf=request.stream.read())
if hasattr(request, 'content'):
tempfile = BytesIO(request.content)
elif hasattr(request, 'read'):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be else, or you could end up with no tempfile.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect this entire block could be better. We shouldn't be doing guesswork here.

tempfile = BytesIO(request.read())
tempfile.name = new_filename
filestorage = FileStorage(tempfile,
filestorage = FileStorage(
tempfile,
filename=new_filename,
content_type=request.headers['content-type'])
content_type=request.headers['content-type']
)
return filestorage


Expand All @@ -49,7 +48,7 @@ def resize_image(requestfile, maxsize=(320, 240)):
img.thumbnail(maxsize, Image.ANTIALIAS)
boximg = Image.new('RGBA', (img.size[0], img.size[1]), (255, 255, 255, 0))
boximg.paste(img, (0, 0))
savefile = StringIO()
savefile = BytesIO()
if fileext in ['jpg', 'jpeg']:
savefile.name = secure_filename(".".join(requestfile.filename.split('.')[:-1]) + ".png")
boximg.save(savefile, format="PNG")
Expand Down
2 changes: 1 addition & 1 deletion hgtv/views/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def channel_edit(channel):
if channel.userid == current_auth.user.userid:
form.type.choices = [(1, CHANNEL_TYPE[1])]
else:
choices = CHANNEL_TYPE.items()
choices = list(CHANNEL_TYPE.items()) # requires list()
choices.pop(0)
choices.pop(0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comment explaining why the first two items are being popped?

form.type.choices = choices
Expand Down
2 changes: 1 addition & 1 deletion hgtv/views/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def index():

@app.route('/search')
def search():
return render_message(title="No search", message=u"Search hasn’t been implemented yet.")
return render_message(title="No search", message="Search hasn’t been implemented yet.")


@app.route('/service-worker.js', methods=['GET'])
Expand Down
8 changes: 4 additions & 4 deletions hgtv/views/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def login():
@app.route('/logout')
@lastuser.logout_handler
def logout():
flash(u"You are now logged out", category='info')
flash("You are now logged out", category='info')
return get_next_url()


Expand All @@ -41,7 +41,7 @@ def lastuser_error(error, error_description=None, error_uri=None):
if error == 'access_denied':
flash("You denied the request to login", category='error')
return redirect(get_next_url())
return Response(u"Error: %s\n"
u"Description: %s\n"
u"URI: %s" % (error, error_description, error_uri),
return Response("Error: %s\n"
"Description: %s\n"
"URI: %s" % (error, error_description, error_uri),
mimetype="text/plain")
Loading