diff --git a/pagure/api/fork.py b/pagure/api/fork.py index bfd0068..14252cf 100644 --- a/pagure/api/fork.py +++ b/pagure/api/fork.py @@ -24,7 +24,7 @@ import pagure.lib.tasks from pagure.api import (API, api_method, api_login_required, APIERROR, get_authorized_api_project) from pagure.config import config as pagure_config -from pagure.utils import is_repo_committer, api_authenticated +from pagure.utils import is_repo_committer, api_authenticated, is_true _log = logging.getLogger(__name__) @@ -148,8 +148,9 @@ def api_pull_request_views(repo, username=None, namespace=None): assignee = flask.request.args.get('assignee', None) author = flask.request.args.get('author', None) + status_text = ("%s" % status).lower() requests = [] - if str(status).lower() in ['0', 'false', 'closed']: + if status_text in ['0', 'false', 'closed']: requests = pagure.lib.search_pull_requests( flask.g.session, project_id=repo.id, @@ -157,7 +158,7 @@ def api_pull_request_views(repo, username=None, namespace=None): assignee=assignee, author=author) - elif str(status).lower() == 'all': + elif status_text == 'all': requests = pagure.lib.search_pull_requests( flask.g.session, project_id=repo.id, @@ -864,7 +865,7 @@ def api_subscribe_pull_request( form = pagure.forms.SubscribtionForm(csrf_enabled=False) if form.validate_on_submit(): - status = str(form.status.data).strip().lower() in ['1', 'true'] + status = is_true(form.status.data) try: # Toggle subscribtion message = pagure.lib.set_watch_obj( diff --git a/pagure/api/group.py b/pagure/api/group.py index 4812e3b..a5e7ba1 100644 --- a/pagure/api/group.py +++ b/pagure/api/group.py @@ -17,6 +17,7 @@ import pagure import pagure.exceptions import pagure.lib from pagure.api import API, APIERROR, api_method, api_login_optional +from pagure.utils import is_true @API.route('/groups/') @@ -55,11 +56,7 @@ def api_groups(): ''' pattern = flask.request.args.get('pattern', None) - extended = flask.request.args.get('extended', None) - if str(extended).lower() in ['1', 'true']: - extended = True - else: - extended = False + extended = is_true(flask.request.args.get('extended', False)) if pattern is not None and not pattern.endswith('*'): pattern += '*' diff --git a/pagure/api/issue.py b/pagure/api/issue.py index 0a383a0..4134a8b 100644 --- a/pagure/api/issue.py +++ b/pagure/api/issue.py @@ -29,6 +29,7 @@ from pagure.utils import ( is_repo_committer, is_repo_user, urlpattern, + is_true, ) @@ -261,7 +262,7 @@ def api_new_issue(repo, username=None, namespace=None): title = form.title.data content = form.issue_content.data milestone = form.milestone.data or None - private = str(form.private.data).lower() in ['true', '1'] + private = is_true(form.private.data) priority = form.priority.data or None assignee = flask.request.form.get( 'assignee', '').strip() or None @@ -453,10 +454,7 @@ def api_view_issues(repo, username=None, namespace=None): milestone = flask.request.args.getlist('milestones', None) no_stones = flask.request.args.get('no_stones', None) if no_stones is not None: - if str(no_stones).lower() in ['1', 'true', 't']: - no_stones = True - else: - no_stones = False + no_stones = is_true(no_stones) priority = flask.request.args.get('priority', None) since = flask.request.args.get('since', None) order = flask.request.args.get('order', None) @@ -601,9 +599,7 @@ def api_view_issue(repo, issueid, username=None, namespace=None): } """ - comments = flask.request.args.get('comments', True) - if str(comments).lower() in ['0', 'False']: - comments = False + comments = is_true(flask.request.args.get('comments', True)) repo = _get_repo(repo, username, namespace) _check_issue_tracker(repo) @@ -1155,7 +1151,7 @@ def api_subscribe_issue(repo, issueid, username=None, namespace=None): form = pagure.forms.SubscribtionForm(csrf_enabled=False) if form.validate_on_submit(): - status = str(form.status.data).strip().lower() in ['1', 'true'] + status = is_true(form.status.data) try: # Toggle subscribtion message = pagure.lib.set_watch_obj( diff --git a/pagure/api/project.py b/pagure/api/project.py index 7455452..73a58c1 100644 --- a/pagure/api/project.py +++ b/pagure/api/project.py @@ -83,10 +83,8 @@ def api_git_tags(repo, username=None, namespace=None): } """ - with_commits = flask.request.values.get('with_commits', None) or False - - if str(with_commits).lower() in ['1', 'true']: - with_commits = True + with_commits = pagure.utils.is_true( + flask.request.values.get('with_commits', False)) repo = get_authorized_api_project( flask.g.session, repo, user=username, namespace=namespace) @@ -542,18 +540,13 @@ def api_projects(): namespace = flask.request.values.get('namespace', None) owner = flask.request.values.get('owner', None) pattern = flask.request.values.get('pattern', None) - short = flask.request.values.get('short', None) + short = pagure.utils.is_true( + flask.request.values.get('short', False)) page = flask.request.values.get('page', None) per_page = flask.request.values.get('per_page', None) - if str(fork).lower() in ['1', 'true']: - fork = True - elif str(fork).lower() in ['0', 'false']: - fork = False - if str(short).lower() in ['1', 'true']: - short = True - else: - short = False + if fork is not None: + fork = pagure.utils.is_true(fork) private = False if pagure.utils.authenticated() \ @@ -721,9 +714,9 @@ def api_project(repo, username=None, namespace=None): repo = get_authorized_api_project( flask.g.session, repo, user=username, namespace=namespace) - expand_group = str( - flask.request.values.get('expand_group', None) - ).lower() in ['1', 't', 'True'] + expand_group = pagure.utils.is_true( + flask.request.values.get('expand_group', False) + ) if repo is None: raise pagure.exceptions.APIError(404, error_code=APIERROR.ENOPROJECT) @@ -1206,7 +1199,7 @@ def api_generate_acls(repo, username=None, namespace=None): json = flask.request.get_json(force=True, silent=True) or {} wait = json.get('wait', False) else: - wait = str(flask.request.form.get('wait')).lower() in ['true', '1'] + wait = pagure.utils.is_true(flask.request.form.get('wait')) try: task = pagure.lib.git.generate_gitolite_acls( diff --git a/pagure/api/user.py b/pagure/api/user.py index 0032395..6ea2b44 100644 --- a/pagure/api/user.py +++ b/pagure/api/user.py @@ -16,11 +16,13 @@ from math import ceil import arrow import flask +import six import pagure import pagure.exceptions import pagure.lib from pagure.api import API, api_method, APIERROR +from pagure.utils import is_true def _get_user(username): @@ -287,10 +289,7 @@ def api_view_user_issues(username): milestone = flask.request.args.getlist('milestones', None) no_stones = flask.request.args.get('no_stones', None) if no_stones is not None: - if str(no_stones).lower() in ['1', 'true', 't']: - no_stones = True - else: - no_stones = False + no_stones = is_true(no_stones) since = flask.request.args.get('since', None) order = flask.request.args.get('order', None) order_key = flask.request.args.get('order_key', None) @@ -591,7 +590,7 @@ def api_view_user_activity_date(username, date): } """ # noqa - grouped = str(flask.request.args.get('grouped')).lower() in ['1', 'true'] + grouped = is_true(flask.request.args.get('grouped')) tz = flask.request.args.get('tz', 'UTC') try: @@ -619,7 +618,7 @@ def api_view_user_activity_date(username, date): if len(commits[project]) == 1: tmp = dict( description_mk=pagure.lib.text2markdown( - str(commits[project][0])) + six.text_type(commits[project][0])) ) else: tmp = dict( @@ -634,7 +633,8 @@ def api_view_user_activity_date(username, date): for act in activities: activity = act.to_json(public=True) - activity['description_mk'] = pagure.lib.text2markdown(str(act)) + activity['description_mk'] = pagure.lib.text2markdown( + six.text_type(act)) js_act.append(activity) jsonout = flask.jsonify( diff --git a/pagure/forms.py b/pagure/forms.py index c20a0f0..a1bb3a6 100644 --- a/pagure/forms.py +++ b/pagure/forms.py @@ -57,7 +57,7 @@ class PagureForm(FlaskForm): def convert_value(val): """ Convert the provided values to strings when possible. """ if val: - if not isinstance(val, (list, tuple, six.string_types)): + if not isinstance(val, (list, tuple, six.text_type)): return val.decode('utf-8') elif isinstance(val, six.string_types): return val diff --git a/pagure/hooks/files/default_hook.py b/pagure/hooks/files/default_hook.py index 16b6e06..371c37d 100755 --- a/pagure/hooks/files/default_hook.py +++ b/pagure/hooks/files/default_hook.py @@ -77,9 +77,7 @@ def send_notifications(session, project, refname, revs, forced): authors = [] for author in auths: - if isinstance(author, six.string_types): - author = author - else: + if not isinstance(author, six.string_types): author = author.to_json(public=True) authors.append(author) diff --git a/pagure/hooks/files/git_multimail.py b/pagure/hooks/files/git_multimail.py index 83ddf52..e096d4b 100755 --- a/pagure/hooks/files/git_multimail.py +++ b/pagure/hooks/files/git_multimail.py @@ -47,7 +47,7 @@ See the accompanying README file for the complete documentation. """ -from __future__ import unicode_literals +from __future__ import print_function, unicode_literals import sys import os @@ -537,6 +537,7 @@ class CommitSet(object): return i < len(self) and self._names[i].startswith(sha1_abbrev) +@six.python_2_unicode_compatible class GitObject(object): def __init__(self, sha1, type=None): if sha1 == ZEROS: @@ -894,9 +895,9 @@ class ReferenceChange(Change): values['short_refname'] = self.short_refname values['msgid'] = self.msgid values['recipients'] = self.recipients - values['oldrev'] = str(self.old) + values['oldrev'] = "%s" % self.old values['oldrev_short'] = self.old.short - values['newrev'] = str(self.new) + values['newrev'] = "%s" % self.new values['newrev_short'] = self.new.short if self.old: @@ -1412,7 +1413,7 @@ class SendMailer(Mailer): except OSError as e: sys.stderr.write( '*** Cannot execute command: %s\n' % ' '.join(self.command) - + '*** %s\n' % str(e) + + '*** %s\n' % e + '*** Try setting multimailhook.mailer to "smtp"\n' '*** to send emails without using the sendmail command.\n' ) @@ -1453,7 +1454,7 @@ class SMTPMailer(Mailer): sys.stderr.write( '*** Error establishing SMTP connection to %s***\n' % self.smtpserver) - sys.stderr.write('*** %s\n' % str(e)) + sys.stderr.write('*** %s\n' % e) sys.exit(1) def __del__(self): @@ -1469,7 +1470,7 @@ class SMTPMailer(Mailer): self.smtp.sendmail(self.envelopesender, to_addrs, msg) except Exception as e: sys.stderr.write('*** Error sending email***\n') - sys.stderr.write('*** %s\n' % str(e)) + sys.stderr.write('*** %s\n' % e) self.smtp.quit() sys.exit(1) @@ -2141,7 +2142,7 @@ class GitoliteEnvironmentMixin(Environment): return self.osenv.get('GL_USER', 'unknown user') -class IncrementalDateTime(object): +class IncrementalDateTime(six.Iterator): """Simple wrapper to give incremental date/times. Each call will result in a date/time a second later than the @@ -2588,7 +2589,8 @@ def main(args): else: run_as_post_receive_hook(environment, mailer) except ConfigurationException as e: - sys.exit(str(e)) + print(e, file=sys.stderr) + sys.exit(1) if __name__ == '__main__': diff --git a/pagure/internal/__init__.py b/pagure/internal/__init__.py index e0fed81..5282f64 100644 --- a/pagure/internal/__init__.py +++ b/pagure/internal/__init__.py @@ -606,7 +606,7 @@ def task_info(taskid): if task.ready(): result = task.get(timeout=0, propagate=False) if isinstance(result, Exception): - result = str(result) + result = "%s" % result return flask.jsonify({'results': result}) else: flask.abort(418) diff --git a/pagure/lib/__init__.py b/pagure/lib/__init__.py index 931abe3..1a0fa3c 100644 --- a/pagure/lib/__init__.py +++ b/pagure/lib/__init__.py @@ -122,7 +122,7 @@ def create_session(db_url=None, debug=False, pool_recycle=3600): global SESSIONMAKER if SESSIONMAKER is None or ( - db_url and db_url != str(SESSIONMAKER.kw['bind'].engine.url)): + db_url and db_url != ("%s" % SESSIONMAKER.kw['bind'].engine.url)): if db_url is None: raise ValueError("First call to create_session needs db_url") if db_url.startswith('postgres'): # pragma: no cover @@ -805,7 +805,7 @@ def remove_issue_dependency( })) return 'Issue **un**marked as depending on: #%s' % ' #'.join( - [str(id) for id in parent_del]) + [("%s" % id) for id in parent_del]) def remove_tags(session, project, tags, gitfolder, user): @@ -1641,7 +1641,7 @@ def new_issue(session, repo, title, content, user, ticketfolder, issue_id=None, priority = None if priorities \ and priority is not None \ - and str(priority) not in priorities: + and ("%s" % priority) not in priorities: raise pagure.exceptions.PagureException( 'You are trying to create an issue with a priority that does ' 'not exist in the project.') @@ -1907,7 +1907,8 @@ def edit_issue(session, issue, ticketfolder, user, repo=None, except (ValueError, TypeError): priority = None - if str(priority) not in priorities: + priority_string = "%s" % priority + if priority_string not in priorities: priority = None if priority != issue.priority: @@ -1915,10 +1916,10 @@ def edit_issue(session, issue, ticketfolder, user, repo=None, issue.priority = priority edit.append('priority') msg = 'Issue priority set to: %s' % ( - priorities[str(priority)] if priority else None) + priorities[priority_string] if priority else None) if old_priority: msg += ' (was: %s)' % priorities.get( - str(old_priority), old_priority) + "%s" % old_priority, old_priority) messages.append(msg) if private in [True, False] and private != issue.private: old_private = issue.private @@ -2512,7 +2513,8 @@ def search_issues( query = query.filter(model.Issue.uid.in_(list(final_set))) if assignee is not None: - if str(assignee).lower() not in ['false', '0', 'true', '1']: + assignee = "%s" % assignee + if not pagure.utils.is_true(assignee, ['false', '0', 'true', '1']): user2 = aliased(model.User) if assignee.startswith('!'): sub = session.query( @@ -2532,7 +2534,7 @@ def search_issues( ).filter( user2.user == assignee ) - elif str(assignee).lower() in ['true', '1']: + elif pagure.utils.is_true(assignee): query = query.filter( model.Issue.assignee_id.isnot(None) ) @@ -2666,7 +2668,7 @@ def search_issues( elif order_key in model.Issue.__table__.columns.keys(): column = getattr(model.Issue, order_key) - if str(column.type) == 'TEXT': + if ("%s" % column.type) == 'TEXT': column = func.lower(column) # The priority is sorted differently because it is by weight and the lower @@ -2787,7 +2789,8 @@ def search_pull_requests( ) if assignee is not None: - if str(assignee).lower() not in ['false', '0', 'true', '1']: + assignee = "%s" % assignee + if not pagure.utils.is_true(assignee, ['false', '0', 'true', '1']): user2 = aliased(model.User) if assignee.startswith('!'): sub = session.query( @@ -2807,7 +2810,7 @@ def search_pull_requests( ).filter( user2.user == assignee ) - elif str(assignee).lower() in ['true', '1']: + elif pagure.utils.is_true(assignee): query = query.filter( model.PullRequest.assignee_id.isnot(None) ) @@ -3145,9 +3148,6 @@ def avatar_url_from_email(email, size=64, default='retro', dns=False): """ Our own implementation since fas doesn't support this nicely yet. """ - if not isinstance(email, six.string_types): - email = email.encode('utf-8') - if dns: # pragma: no cover # This makes an extra DNS SRV query, which can slow down our webapps. # It is necessary for libravatar federation, though. @@ -3159,8 +3159,7 @@ def avatar_url_from_email(email, size=64, default='retro', dns=False): ) else: query = urlencode({'s': size, 'd': default}) - if six.PY3: - email = email.encode('utf-8') + email = email.encode('utf-8') hashhex = hashlib.sha256(email).hexdigest() return "https://seccdn.libravatar.org/avatar/%s?%s" % ( hashhex, query) @@ -3801,7 +3800,7 @@ def text2markdown(text, extended=True, readme=False): except Exception: _log.debug( 'A markdown error occured while processing: ``%s``', - str(text)) + text) return clean_input(text) return '' diff --git a/pagure/lib/encoding_utils.py b/pagure/lib/encoding_utils.py index 60c1493..aaeb5a3 100644 --- a/pagure/lib/encoding_utils.py +++ b/pagure/lib/encoding_utils.py @@ -100,7 +100,7 @@ def guess_encodings(data): sorted_encodings = sorted( encodings, key=lambda guess: guess.confidence, reverse=True) - _log.debug('Possible encodings: ' + str(sorted_encodings)) + _log.debug('Possible encodings: %s' % sorted_encodings) return sorted_encodings diff --git a/pagure/lib/git.py b/pagure/lib/git.py index 3fa6f95..12b7d93 100644 --- a/pagure/lib/git.py +++ b/pagure/lib/git.py @@ -725,9 +725,9 @@ def update_request_from_git( ) status = json_data.get('status') - if str(status).lower() == 'true': + if pagure.utils.is_true(status): status = 'Open' - elif str(status).lower() == 'false': + elif pagure.utils.is_true(status, ['false']): status = 'Merged' # Create new request diff --git a/pagure/lib/git_auth.py b/pagure/lib/git_auth.py index 8ce78e5..64a520f 100644 --- a/pagure/lib/git_auth.py +++ b/pagure/lib/git_auth.py @@ -15,6 +15,7 @@ import os import pkg_resources import subprocess import tempfile +from io import open import werkzeug from six import with_metaclass @@ -420,7 +421,7 @@ class Gitolite2Auth(GitAuthHelper): return _log.info('Writing the configuration to: %s', configfile) - with open(configfile, 'w') as stream: + with open(configfile, 'w', encoding="utf-8") as stream: if preconfig: stream.write(preconfig + '\n') stream.write('# end of header\n') @@ -553,7 +554,7 @@ class Gitolite2Auth(GitAuthHelper): return _log.info('Writing the configuration to: %s', configfile) - with open(configfile, 'w') as stream: + with open(configfile, 'w', encoding="utf-8") as stream: if preconfig: stream.write(preconfig + '\n') stream.write('# end of header\n') diff --git a/pagure/lib/lib_ci.py b/pagure/lib/lib_ci.py index 07e1b3a..7208fda 100644 --- a/pagure/lib/lib_ci.py +++ b/pagure/lib/lib_ci.py @@ -88,7 +88,7 @@ def process_jenkins_build( comment, percent = BUILD_STATS[result] # Adding build ID to the CI type - username = project.ci_hook.ci_type + " #" + str(build_id) + username = "%s #%s" % (project.ci_hook.ci_type, build_id) pagure.lib.add_pull_request_flag( session, diff --git a/pagure/lib/login.py b/pagure/lib/login.py index c8f117b..95a8fa3 100644 --- a/pagure/lib/login.py +++ b/pagure/lib/login.py @@ -78,7 +78,7 @@ def check_password(entered_password, user_password, seed=None): if not isinstance(entered_password, six.text_type): raise ValueError("Entered password is not unicode text") if isinstance(user_password, six.text_type): - raise ValueError("DB password is not bytes") + user_password = user_password.encode("utf-8") if not user_password.count(b'$') >= 2: raise pagure.exceptions.PagureException( diff --git a/pagure/lib/model.py b/pagure/lib/model.py index 7571fee..6d2de48 100644 --- a/pagure/lib/model.py +++ b/pagure/lib/model.py @@ -21,6 +21,7 @@ import json import operator import re +import six import sqlalchemy as sa from sqlalchemy import create_engine, MetaData @@ -32,6 +33,7 @@ from sqlalchemy.orm import scoped_session from sqlalchemy.orm import relation import pagure.exceptions +from pagure.utils import is_true CONVENTION = { @@ -160,6 +162,10 @@ def create_default_status(session, acls=None): _log.debug('Access level %s could not be added', access) +def arrow_ts(value): + return "%s" % arrow.get(value).timestamp + + class AccessLevels(BASE): ''' Different access levels a user/group can have for a project ''' __tablename__ = 'access_levels' @@ -265,7 +271,7 @@ class User(BASE): for key in default: if key not in current: current[key] = default[key] - elif str(current[key]).lower() in ['true', 'y']: + elif is_true(current[key]): current[key] = True return current else: @@ -550,7 +556,7 @@ class Project(BASE): current[key] = default[key] elif key == 'Minimum_score_to_merge_pull-request': current[key] = int(current[key]) - elif str(current[key]).lower() in ['true', 'y']: + elif is_true(current[key]): current[key] = True return current else: @@ -897,8 +903,8 @@ class Project(BASE): 'namespace': self.namespace, 'parent': self.parent.to_json( public=public, api=api) if self.parent else None, - 'date_created': str(arrow.get(self.date_created).timestamp), - 'date_modified': str(arrow.get(self.date_modified).timestamp), + 'date_created': arrow_ts(self.date_created), + 'date_modified': arrow_ts(self.date_modified), 'user': self.user.to_json(public=public), 'access_users': self.access_users_json, 'access_groups': self.access_groups_json, @@ -1210,7 +1216,7 @@ class Issue(BASE): (link, filename, display_name, comment.date_created.strftime( '%Y-%m-%d %H:%M:%S'), - str(comment.id)) + "%s" % comment.id) ) return attachments @@ -1276,15 +1282,14 @@ class Issue(BASE): 'content': self.content, 'status': self.status, 'close_status': self.close_status, - 'date_created': str(arrow.get(self.date_created).timestamp), - 'last_updated': str(arrow.get(self.last_updated).timestamp), - 'closed_at': str(arrow.get(self.closed_at).timestamp) - if self.closed_at else None, + 'date_created': arrow_ts(self.date_created), + 'last_updated': arrow_ts(self.last_updated), + 'closed_at': arrow_ts(self.closed_at) if self.closed_at else None, 'user': self.user.to_json(public=public), 'private': self.private, 'tags': self.tags_text, - 'depends': [str(item) for item in self.depending_text], - 'blocks': [str(item) for item in self.blocking_text], + 'depends': ["%s" % item for item in self.depending_text], + 'blocks': ["%s" % item for item in self.blocking_text], 'assignee': self.assignee.to_json( public=public) if self.assignee else None, 'priority': self.priority, @@ -1431,10 +1436,9 @@ class IssueComment(BASE): 'id': self.id, 'comment': self.comment, 'parent': self.parent_id, - 'date_created': str(arrow.get(self.date_created).timestamp), + 'date_created': arrow_ts(self.date_created), 'user': self.user.to_json(public=public), - 'edited_on': str(arrow.get(self.edited_on).timestamp) - if self.edited_on else None, + 'edited_on': arrow_ts(self.edited_on) if self.edited_on else None, 'editor': self.editor.to_json(public=public) if self.editor_id else None, 'notification': self.notification, @@ -1896,11 +1900,10 @@ class PullRequest(BASE): 'repo_from': self.project_from.to_json( public=public, api=api) if self.project_from else None, 'remote_git': self.remote_git, - 'date_created': str(arrow.get(self.date_created).timestamp), - 'updated_on': str(arrow.get(self.updated_on).timestamp), - 'last_updated': str(arrow.get(self.last_updated).timestamp), - 'closed_at': str(arrow.get(self.closed_at).timestamp) - if self.closed_at else None, + 'date_created': arrow_ts(self.date_created), + 'updated_on': arrow_ts(self.updated_on), + 'last_updated': arrow_ts(self.last_updated), + 'closed_at': arrow_ts(self.closed_at) if self.closed_at else None, 'user': self.user.to_json(public=public), 'assignee': self.assignee.to_json( public=public) if self.assignee else None, @@ -2020,10 +2023,9 @@ class PullRequestComment(BASE): 'line': self.line, 'comment': self.comment, 'parent': self.parent_id, - 'date_created': str(arrow.get(self.date_created).timestamp), + 'date_created': arrow_ts(self.date_created), 'user': self.user.to_json(public=public), - 'edited_on': str(arrow.get(self.edited_on).timestamp) - if self.edited_on else None, + 'edited_on': arrow_ts(self.edited_on) if self.edited_on else None, 'editor': self.editor.to_json(public=public) if self.editor_id else None, 'notification': self.notification, @@ -2112,7 +2114,7 @@ class PullRequestFlag(BASE): 'comment': self.comment, 'status': self.status, 'url': self.url, - 'date_created': str(arrow.get(self.date_created).timestamp), + 'date_created': arrow_ts(self.date_created), 'user': self.user.to_json(public=public), } @@ -2206,7 +2208,7 @@ class CommitFlag(BASE): 'comment': self.comment, 'status': self.status, 'url': self.url, - 'date_created': str(arrow.get(self.date_created).timestamp), + 'date_created': arrow_ts(self.date_created), 'user': self.user.to_json(public=public), } @@ -2324,7 +2326,7 @@ class PagureGroup(BASE): 'description': self.description, 'group_type': self.group_type, 'creator': self.creator.to_json(public=public), - 'date_created': str(arrow.get(self.created).timestamp), + 'date_created': arrow_ts(self.created), 'members': [user.username for user in self.users] } @@ -2452,6 +2454,7 @@ class Watcher(BASE): ) +@six.python_2_unicode_compatible class PagureLog(BASE): """ Log user's actions. @@ -2533,7 +2536,7 @@ class PagureLog(BASE): 'type': self.log_type, 'ref_id': self.ref_id, 'date': self.date.strftime('%Y-%m-%d'), - 'date_created': str(arrow.get(self.date_created).timestamp), + 'date_created': arrow_ts(self.date_created), 'user': self.user.to_json(public=public), } return output @@ -2766,7 +2769,7 @@ class Token(BASE): def acls_list(self): ''' Return a list containing the name of each ACLs this token has. ''' - return sorted([str(acl.name) for acl in self.acls]) + return sorted(["%s" % acl.name for acl in self.acls]) @property def acls_list_pretty(self): diff --git a/pagure/lib/notify.py b/pagure/lib/notify.py index 5097418..d46bfb1 100644 --- a/pagure/lib/notify.py +++ b/pagure/lib/notify.py @@ -242,7 +242,7 @@ def _build_url(*args): ''' Build a URL from a given list of arguments. ''' items = [] for idx, arg in enumerate(args): - arg = str(arg) + arg = "%s" % arg if arg.startswith('/'): arg = arg[1:] if arg.endswith('/') and not idx + 1 == len(args): @@ -331,7 +331,7 @@ def send_email(text, subject, to_mail, key = (b'<' + mail_id.encode("utf-8") + b'>' + salt + mailto.encode("utf-8")) - if six.PY3 and isinstance(key, str): + if isinstance(key, six.text_type): key = key.encode('utf-8') mhash = hashlib.sha512(key) diff --git a/pagure/lib/tasks_services.py b/pagure/lib/tasks_services.py index 5829664..4273318 100644 --- a/pagure/lib/tasks_services.py +++ b/pagure/lib/tasks_services.py @@ -68,15 +68,15 @@ def call_web_hooks(project, topic, msg, urls): topic=topic.decode('utf-8'), msg=msg, timestamp=int(time.time()), - msg_id=str(year) + '-' + str(uuid.uuid4()), + msg_id="%s-%s" % (year, uuid.uuid4()), i=_i, ) content = json.dumps(msg) hashhex = hmac.new( - str(project.hook_token), content, hashlib.sha1).hexdigest() + "%s" % project.hook_token, content, hashlib.sha1).hexdigest() hashhex256 = hmac.new( - str(project.hook_token), content, hashlib.sha256).hexdigest() + "%s" % project.hook_token, content, hashlib.sha256).hexdigest() headers = { 'X-Pagure': pagure_config['APP_URL'], 'X-Pagure-project': project.fullname, diff --git a/pagure/perfrepo.py b/pagure/perfrepo.py index 88ae083..71f080e 100644 --- a/pagure/perfrepo.py +++ b/pagure/perfrepo.py @@ -48,7 +48,7 @@ class PerfRepoMeta(type): return real -class FakeWalker(object): +class FakeWalker(six.Iterator): def __init__(self, parent): self.parent = parent self.wid = STATS['counters']['walks'] @@ -72,7 +72,7 @@ class FakeWalker(object): def __next__(self): STATS['walks'][self.wid]['steps'] += 1 TOTALS['steps'] += 1 - resp = next(self.parent) + resp = next(iter(self.parent)) return resp @@ -97,7 +97,7 @@ class FakeDiffPatch(object): return getattr(self.parent, attr) -class FakeDiffer(object): +class FakeDiffer(six.Iterator): def __init__(self, parent): self.parent = parent self.iter = None @@ -118,7 +118,7 @@ class FakeDiffer(object): def __iter__(self): STATS['diffs'][self.did]['iter'] = traceback.extract_stack(limit=2)[0] - self.iter = self.parent.__iter__() + self.iter = iter(self.parent) return self def __next__(self): @@ -134,7 +134,7 @@ class FakeDiffer(object): return len(self.parent) -class PerfRepo(six.with_metaclass(PerfRepoMeta, object)): +class PerfRepo(six.with_metaclass(PerfRepoMeta, six.Iterator)): """ An utility class allowing to go around pygit2's inability to be stable. @@ -185,7 +185,7 @@ class PerfRepo(six.with_metaclass(PerfRepoMeta, object)): 'iter': traceback.extract_stack(limit=3)[0]} TOTALS['walks'] += 1 - self.iter = self.repo.__iter__() + self.iter = iter(self.repo) return self def __next__(self): diff --git a/pagure/ui/app.py b/pagure/ui/app.py index e4e7191..2f976a7 100644 --- a/pagure/ui/app.py +++ b/pagure/ui/app.py @@ -31,6 +31,7 @@ from pagure.utils import ( is_safe_url, login_required, get_task_redirect_url, + is_true, ) @@ -179,11 +180,7 @@ def search(): stype = flask.request.args.get('type', 'projects') term = flask.request.args.get('term') page = flask.request.args.get('page', 1) - direct = flask.request.values.get('direct', None) - if str(direct).lower() in ['1', 'true']: - direct = True - else: - direct = False + direct = is_true(flask.request.values.get('direct', False)) try: page = int(page) @@ -292,7 +289,7 @@ def view_projects(pattern=None, namespace=None): select = 'projects' # If forks is specified, we want both forks and projects - if str(forks).lower() in ['true', '1']: + if is_true(forks): forks = None select = 'projects_forks' else: @@ -556,11 +553,7 @@ def wait_task(taskid): """ Shows a wait page until the task finishes. """ task = pagure.lib.tasks.get_result(taskid) - is_js = flask.request.args.get('js') - if str(is_js).lower() == '1': - is_js = True - else: - is_js = False + is_js = is_true(flask.request.args.get('js')) prev = flask.request.args.get('prev') if not is_safe_url(prev): diff --git a/pagure/ui/filters.py b/pagure/ui/filters.py index 6a379a9..cdbd130 100644 --- a/pagure/ui/filters.py +++ b/pagure/ui/filters.py @@ -33,7 +33,7 @@ import pagure.lib import pagure.forms from pagure.config import config as pagure_config from pagure.ui import UI_NS -from pagure.utils import authenticated, is_repo_committer +from pagure.utils import authenticated, is_repo_committer, is_true # Jinja filters @@ -198,10 +198,9 @@ def format_loc(loc, commit=None, filename=None, tree_id=None, prequest=None, templ_delete = '' templ_edit = '' templ_edited = '' - status = str(comment.parent.status).lower() if authenticated() and ( ( - status in ['true', 'open'] + is_true(comment.parent.status, ['true', 'open']) and comment.user.user == flask.g.fas_user.username ) or is_repo_committer(comment.parent.project)): @@ -300,7 +299,7 @@ def blame_loc(loc, repo, username, blame): if not isinstance(loc, six.text_type): raise ValueError( - '"loc" must be a unicode string, not ' + str(type(loc))) + '"loc" must be a unicode string, not %s' % type(loc)) output = [ '
', @@ -374,11 +373,8 @@ def text_wraps(text, size=10): def avatar(packager, size=64): """ Template filter that returns html for avatar of any given Username. """ - if six.PY3: - if isinstance(packager, six.string_types): - packager = packager.encode('utf-8').decode('utf-8') - else: - packager = packager.decode('utf-8') + if not isinstance(packager, six.text_type): + packager = packager.decode('utf-8') if '@' not in packager: user = pagure.lib.search_user(flask.g.session, username=packager) @@ -402,7 +398,7 @@ def avatar_url(email, size=64): @UI_NS.app_template_filter('short') def shorted_commit(cid): """Gets short version of the commit id""" - return str(cid)[:pagure_config['SHORT_LENGTH']] + return ("%s" % cid)[:pagure_config['SHORT_LENGTH']] @UI_NS.app_template_filter('markdown') @@ -536,7 +532,7 @@ def insert_div(content): if row.startswith('
' in row: - row = str(row).replace( + row = ("%s" % row).replace( '

', '

' '  ' diff --git a/pagure/ui/fork.py b/pagure/ui/fork.py index a86e74f..bb4ee39 100644 --- a/pagure/ui/fork.py +++ b/pagure/ui/fork.py @@ -36,7 +36,7 @@ import pagure.forms from pagure.config import config as pagure_config from pagure.ui import UI_NS from pagure.utils import ( - login_required, __get_file_in_tree, get_parent_repo_path) + login_required, __get_file_in_tree, get_parent_repo_path, is_true) _log = logging.getLogger(__name__) @@ -76,12 +76,12 @@ def request_pulls(repo, username=None, namespace=None): if not repo.settings.get('pull_requests', True): flask.abort(404, 'No pull-requests found for this project') - if str(status).lower() in ['false', '0']: + if is_true(status, ['false', '0']): status = False - elif str(status).lower() in ['all']: + elif is_true(status, ['all']): status = None - if str(status).lower() in ['true', '1', 'open']: + if is_true(status, ['true', '1', 'open']): requests = pagure.lib.search_pull_requests( flask.g.session, project_id=repo.id, diff --git a/pagure/ui/issues.py b/pagure/ui/issues.py index 35a1f3b..c348ce9 100644 --- a/pagure/ui/issues.py +++ b/pagure/ui/issues.py @@ -42,6 +42,7 @@ from pagure.utils import ( authenticated, login_required, urlpattern, + is_true, ) @@ -248,7 +249,7 @@ def update_issue(repo, issueid, username=None, namespace=None): messages.add(message) # Adjust priority if needed - if str(new_priority) not in repo.priorities: + if "%s" % new_priority not in repo.priorities: new_priority = None # Update core metadata @@ -1022,7 +1023,7 @@ def new_issue(repo, username=None, namespace=None): if repo.default_priority == val: default_priority = key form.priority.data = flask.request.form.get( - 'priority', str(default_priority)) + 'priority', "%s" % default_priority) return flask.render_template( 'new_issue.html', @@ -1360,8 +1361,7 @@ def view_issue_raw_file( """ Displays the raw content of a file of a commit for the specified ticket repo. """ - raw = flask.request.args.get('raw') - raw = str(raw).lower() in ['1', 'true', 't'] + raw = is_true(flask.request.args.get('raw')) repo = flask.g.repo diff --git a/pagure/ui/login.py b/pagure/ui/login.py index 1efcc93..89f6c64 100644 --- a/pagure/ui/login.py +++ b/pagure/ui/login.py @@ -122,7 +122,7 @@ def do_login(): else: password = user_obj.password - if not isinstance(password, six.string_types): + if not isinstance(password, six.text_type): password = password.decode('utf-8') if not password.startswith('$2$'): user_obj.password = generate_hashed_value(form.password.data) diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py index 64953ce..2574c94 100644 --- a/pagure/ui/repo.py +++ b/pagure/ui/repo.py @@ -59,6 +59,7 @@ from pagure.utils import ( __get_file_in_tree, authenticated, login_required, + is_true, stream_template, ) from pagure.decorators import ( @@ -542,7 +543,7 @@ def view_file(repo, identifier, filename, username=None, namespace=None): isbinary = is_binary_string(content.data) if isinstance(content, pygit2.Blob): - rawtext = str(flask.request.args.get('text')).lower() in ['1', 'true'] + rawtext = is_true(flask.request.args.get('text')) ext = filename[filename.rfind('.'):] if ext in ( '.gif', '.png', '.bmp', '.tif', '.tiff', '.jpg', @@ -608,6 +609,8 @@ def view_file(repo, identifier, filename, username=None, namespace=None): content = sorted(content, key=lambda x: x.filemode) for i in content: name, ext = os.path.splitext(i.name) + if not isinstance(name, six.text_type): + name = name.decode("utf-8") if name == 'README': readme_file = __get_file_in_tree( repo_obj, content, [i.name]).data @@ -704,8 +707,6 @@ def view_raw_file( # First commit in the repo diff = commit.tree.diff_to_tree(swap=True) data = diff.patch - if six.PY3: - data = data.encode('utf-8').decode('utf-8') if not data: flask.abort(404, 'No content found') @@ -1534,9 +1535,10 @@ def remove_deploykey(repo, keyid, username=None, namespace=None): form = pagure.forms.ConfirmationForm() if form.validate_on_submit(): - keyids = [str(key.id) for key in repo.deploykeys] + keyids = ["%s" % key.id for key in repo.deploykeys] + keyid = "%s" % keyid - if str(keyid) not in keyids: + if keyid not in keyids: flask.flash( 'Deploy key does not exist in project.', 'error') return flask.redirect(flask.url_for( @@ -1545,7 +1547,7 @@ def remove_deploykey(repo, keyid, username=None, namespace=None): ) for key in repo.deploykeys: - if str(key.id) == str(keyid): + if "%s" % key.id == keyid: flask.g.session.delete(key) break try: @@ -1590,10 +1592,11 @@ def remove_user(repo, userid, username=None, namespace=None): form = pagure.forms.ConfirmationForm() delete_themselves = False if form.validate_on_submit(): - userids = [str(user.id) for user in repo.users] - delete_themselves = str(current_user.id) in userids + userids = ["%s" % user.id for user in repo.users] + delete_themselves = "%s" % current_user.id in userids + userid = "%s" % userid - if str(userid) not in userids: + if userid not in userids: flask.flash('User does not have any access on the repo', 'error') return flask.redirect(flask.url_for( 'ui_ns.view_settings', repo=repo.name, username=username, @@ -1601,7 +1604,7 @@ def remove_user(repo, userid, username=None, namespace=None): ) for u in repo.users: - if str(u.id) == str(userid): + if "%s" % u.id == userid: user = u repo.users.remove(u) break @@ -2134,7 +2137,7 @@ def edit_file(repo, branchname, filename, username=None, namespace=None): else: data = form.content.data - if not isinstance(data, six.string_types): + if not isinstance(data, six.text_type): data = data.decode('utf-8') return flask.render_template( @@ -2308,7 +2311,7 @@ def watch_repo(repo, watch, username=None, namespace=None): if not form.validate_on_submit(): flask.abort(400) - if str(watch) not in ['0', '1', '2', '3', '-1']: + if "%s" % watch not in ['0', '1', '2', '3', '-1']: flask.abort(400) try: @@ -2483,8 +2486,9 @@ def update_custom_keys(repo, username=None, namespace=None): ] custom_keys_notify = [] for idx in range(len(custom_keys)): - custom_keys_notify.append(str( - flask.request.form.get('custom_keys_notify-%s' % (idx + 1)))) + custom_keys_notify.append( + "%s" % flask.request.form.get( + 'custom_keys_notify-%s' % (idx + 1))) try: msg = pagure.lib.set_custom_key_fields( diff --git a/pagure/utils.py b/pagure/utils.py index 4c09271..6ab1ca6 100644 --- a/pagure/utils.py +++ b/pagure/utils.py @@ -332,7 +332,7 @@ def get_task_redirect_url(task, prev): prev=prev) result = task.get(timeout=0, propagate=False) if task.failed(): - flask.flash('Your task failed: %s' % str(result)) + flask.flash('Your task failed: %s' % result) task.forget() return prev if isinstance(result, dict): @@ -401,3 +401,14 @@ def stream_template(app, template_name, **context): rv = t.stream(context) rv.enable_buffering(5) return rv + + +def is_true(value, trueish=('1', 'true', 't', 'y')): + if isinstance(value, bool): + return value + if isinstance(value, six.binary_type): + # In Py3, str(b'true') == "b'true'", not b'true' as in Py2. + value = value.decode() + else: + value = str(value) + return value.strip().lower() in trueish diff --git a/tests/__init__.py b/tests/__init__.py index 2ad6541..c63b04e 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -25,7 +25,7 @@ import sys import tempfile import time import unittest -from io import StringIO +from io import open, StringIO logging.basicConfig(stream=sys.stderr) from bs4 import BeautifulSoup @@ -831,7 +831,7 @@ def add_content_to_git(folder, filename='sources', content='foo'): repo = pygit2.clone_repository(folder, newfolder) # Create a file in that git repo - with open(os.path.join(newfolder, filename), 'a') as stream: + with open(os.path.join(newfolder, filename), 'a', encoding="utf-8") as stream: stream.write('%s\n' % content) repo.index.add(filename) repo.index.write() diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py index ba6dee8..2f06067 100644 --- a/tests/test_pagure_flask_ui_fork.py +++ b/tests/test_pagure_flask_ui_fork.py @@ -22,6 +22,7 @@ import time import os import pygit2 +import six from mock import patch, MagicMock from bs4 import BeautifulSoup @@ -106,6 +107,12 @@ class PagureFlaskForktests(tests.Modeltests): first_commit = repo.revparse_single('HEAD') + def compatible_signature(name, email): + if six.PY2: + name = name.encode("utf-8") + email = email.encode("utf-8") + return pygit2.Signature(name, email) + if mtype == 'merge': with open(os.path.join(repopath, '.gitignore'), 'w') as stream: stream.write('*~') @@ -114,9 +121,9 @@ class PagureFlaskForktests(tests.Modeltests): # Commits the files added tree = clone_repo.index.write_tree() - author = pygit2.Signature( + author = compatible_signature( 'Alice Äuthòr', 'alice@äuthòrs.tld') - committer = pygit2.Signature( + comitter = compatible_signature( 'Cecil Cõmmîttër', 'cecil@cõmmîttërs.tld') clone_repo.create_commit( 'refs/heads/master', diff --git a/tests/test_pagure_flask_ui_login.py b/tests/test_pagure_flask_ui_login.py index be23dd9..d371d11 100644 --- a/tests/test_pagure_flask_ui_login.py +++ b/tests/test_pagure_flask_ui_login.py @@ -280,7 +280,7 @@ class PagureFlaskLogintests(tests.SimplePagureTest): # V1 password password = '%s%s' % ('barpass', None) - if isinstance(password, six.string_types): + if isinstance(password, six.text_type): password = password.encode('utf-8') password = hashlib.sha512(password).hexdigest().encode("utf-8") item.token = None diff --git a/tests/test_pagure_flask_ui_repo.py b/tests/test_pagure_flask_ui_repo.py index 694051f..c63c24d 100644 --- a/tests/test_pagure_flask_ui_repo.py +++ b/tests/test_pagure_flask_ui_repo.py @@ -2578,7 +2578,7 @@ class PagureFlaskRepotests(tests.Modeltests): ncommits=10) tests.add_content_to_git( os.path.join(self.path, 'repos', 'forks', 'pingou', 'test3.git'), - content='✨☃🍰☃✨'.encode('utf-8')) + content='✨☃🍰☃✨') output = self.app.get('/fork/pingou/test3/blame/sources') self.assertEqual(output.status_code, 200) diff --git a/tests/test_pagure_lib_gitolite_config.py b/tests/test_pagure_lib_gitolite_config.py index 97aab36..9fcd83b 100644 --- a/tests/test_pagure_lib_gitolite_config.py +++ b/tests/test_pagure_lib_gitolite_config.py @@ -21,6 +21,7 @@ import sys import tempfile import time import unittest +from io import open import pygit2 from mock import patch, MagicMock @@ -98,7 +99,7 @@ class PagureLibGitoliteConfigtests(tests.Modeltests): stream.write('@group2 = threebean puiterwijk kevin pingou\n') self.postconf = os.path.join(self.path, 'footer_gitolite') - with open(self.postconf, 'w') as stream: + with open(self.postconf, 'w', encoding="utf-8") as stream: stream.write('# end of generated configuration\n') stream.write('# \ó/\n') stream.write('# end of footer\n') diff --git a/tests/test_pagure_lib_login.py b/tests/test_pagure_lib_login.py index 2573405..8bc8c27 100644 --- a/tests/test_pagure_lib_login.py +++ b/tests/test_pagure_lib_login.py @@ -66,7 +66,7 @@ class PagureLibLogintests(tests.Modeltests): # Version 1 password = '%s%s' % ('foo', pagure.config.config.get('PASSWORD_SEED', None)) - if isinstance(password, six.string_types): + if isinstance(password, six.text_type): password = password.encode('utf-8') password = '$1$' + hashlib.sha512(password).hexdigest() password = password.encode("utf-8") @@ -75,7 +75,7 @@ class PagureLibLogintests(tests.Modeltests): # Invalid password - No version password = '%s%s' % ('foo', pagure.config.config.get('PASSWORD_SEED', None)) - if isinstance(password, six.string_types): + if isinstance(password, six.text_type): password = password.encode('utf-8') password = hashlib.sha512(password).hexdigest() password = password.encode("utf-8") @@ -94,7 +94,7 @@ class PagureLibLogintests(tests.Modeltests): password ) password = '%s%s' % ('foo', pagure.config.config.get('PASSWORD_SEED', None)) - if isinstance(password, six.string_types): + if isinstance(password, six.text_type): password = password.encode('utf-8') password = hashlib.sha512(password).hexdigest() password = password.encode("utf-8")