events: add serialization .to_dict() to events based on marshmallow

This commit is contained in:
Daniel Dourvaris 2016-07-06 12:21:03 +03:00
parent a0af559a3d
commit 23d7a947f5
13 changed files with 177 additions and 19 deletions

View file

@ -831,6 +831,19 @@
license = [ pkgs.lib.licenses.bsdOriginal ];
};
};
marshmallow = super.buildPythonPackage {
name = "marshmallow-2.8.0";
buildInputs = with self; [];
doCheck = false;
propagatedBuildInputs = with self; [];
src = fetchurl {
url = "https://pypi.python.org/packages/4f/64/9393d77847d86981c84b88bbea627d30ff71b5ab1402636b366f73737817/marshmallow-2.8.0.tar.gz";
md5 = "204513fc123a3d9bdd7b63b9747f02e6";
};
meta = {
license = [ pkgs.lib.licenses.mit ];
};
};
mccabe = super.buildPythonPackage {
name = "mccabe-0.3";
buildInputs = with self; [];
@ -1355,7 +1368,7 @@
name = "rhodecode-enterprise-ce-4.3.0";
buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner];
doCheck = true;
propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt];
propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu marshmallow msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt];
src = ./.;
meta = {
license = [ { fullName = "AGPLv3, and Commercial License"; } ];
@ -1637,5 +1650,5 @@
### Test requirements
}

View file

@ -84,6 +84,7 @@ iso8601==0.1.11
itsdangerous==0.24
kombu==1.5.1
lxml==3.4.4
marshmallow==2.8.0
mccabe==0.3
meld3==1.0.2
mock==1.0.1

View file

@ -47,9 +47,14 @@ class TestApiUpdateRepo(object):
({'enable_statistics': True}, SAME_AS_UPDATES),
({'enable_locking': True}, SAME_AS_UPDATES),
({'enable_downloads': True}, SAME_AS_UPDATES),
({'name': 'new_repo_name'}, {'repo_name': 'new_repo_name'}),
({'group': 'test_group_for_update'},
{'repo_name': 'test_group_for_update/%s' % UPDATE_REPO_NAME}),
({'name': 'new_repo_name'}, {
'repo_name': 'new_repo_name',
'url': 'http://test.example.com:80/new_repo_name',
}),
({'group': 'test_group_for_update'}, {
'repo_name': 'test_group_for_update/%s' % UPDATE_REPO_NAME,
'url': 'http://test.example.com:80/test_group_for_update/%s' % UPDATE_REPO_NAME
}),
])
def test_api_update_repo(self, updates, expected, backend):
repo_name = UPDATE_REPO_NAME

View file

@ -454,6 +454,7 @@ class PullrequestsController(BaseRepoController):
h.flash(_('Successfully opened new pull request'),
category='success')
except Exception as e:
raise
msg = _('Error occurred during sending pull request')
log.exception(msg)
h.flash(msg, category='error')

View file

@ -19,12 +19,6 @@
from pyramid.threadlocal import get_current_registry
class RhodecodeEvent(object):
"""
Base event class for all Rhodecode events
"""
def trigger(event):
"""
Helper method to send an event. This wraps the pyramid logic to send an
@ -37,6 +31,8 @@ def trigger(event):
registry.notify(event)
from rhodecode.events.base import RhodecodeEvent
from rhodecode.events.user import (
UserPreCreate,
UserPreUpdate,
@ -44,6 +40,7 @@ from rhodecode.events.user import (
)
from rhodecode.events.repo import (
RepoEvent,
RepoPreCreateEvent, RepoCreatedEvent,
RepoPreDeleteEvent, RepoDeletedEvent,
RepoPrePushEvent, RepoPushEvent,
@ -51,6 +48,7 @@ from rhodecode.events.repo import (
)
from rhodecode.events.pullrequest import (
PullRequestEvent,
PullRequestCreateEvent,
PullRequestUpdateEvent,
PullRequestReviewEvent,

69
rhodecode/events/base.py Normal file
View file

@ -0,0 +1,69 @@
# Copyright (C) 2016-2016 RhodeCode GmbH
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
from datetime import datetime
from marshmallow import Schema, fields
from pyramid.threadlocal import get_current_request
from rhodecode.lib.utils2 import AttributeDict
SYSTEM_USER = AttributeDict(dict(
username='__SYSTEM__'
))
class UserSchema(Schema):
"""
Marshmallow schema for a user
"""
username = fields.Str()
class RhodecodeEventSchema(Schema):
"""
Marshmallow schema for a rhodecode event
"""
utc_timestamp = fields.DateTime()
acting_user = fields.Nested(UserSchema)
acting_ip = fields.Str()
class RhodecodeEvent(object):
"""
Base event class for all Rhodecode events
"""
MarshmallowSchema = RhodecodeEventSchema
def __init__(self):
self.request = get_current_request()
self.utc_timestamp = datetime.utcnow()
@property
def acting_user(self):
if self.request:
return self.request.user.get_instance()
return SYSTEM_USER
@property
def acting_ip(self):
if self.request:
return self.request.user.ip_addr
return '<no ip available>'
def as_dict(self):
return self.MarshmallowSchema().dump(self).data

View file

@ -16,15 +16,40 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
from marshmallow import Schema, fields
from rhodecode.events.repo import RepoEvent
def get_pull_request_url(pull_request):
from rhodecode.model.pull_request import PullRequestModel
return PullRequestModel().get_url(pull_request)
class PullRequestSchema(Schema):
"""
Marshmallow schema for a pull request
"""
pull_request_id = fields.Integer()
url = fields.Function(get_pull_request_url)
title = fields.Str()
class PullRequestEventSchema(RepoEvent.MarshmallowSchema):
"""
Marshmallow schema for a pull request event
"""
pullrequest = fields.Nested(PullRequestSchema)
class PullRequestEvent(RepoEvent):
"""
Base class for events acting on a repository.
Base class for pull request events.
:param repo: a :class:`Repository` instance
:param pullrequest: a :class:`PullRequest` instance
"""
MarshmallowSchema = PullRequestEventSchema
def __init__(self, pullrequest):
super(PullRequestEvent, self).__init__(pullrequest.target_repo)
self.pullrequest = pullrequest

View file

@ -16,8 +16,31 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
from marshmallow import Schema, fields
from rhodecode.model.db import Repository, Session
from rhodecode.events import RhodecodeEvent
from rhodecode.events.base import RhodecodeEvent
def get_pull_request_url(repo):
from rhodecode.model.repo import RepoModel
return RepoModel().get_url(repo)
class RepositorySchema(Schema):
"""
Marshmallow schema for a repository
"""
repo_id = fields.Integer()
repo_name = fields.Str()
url = fields.Function(get_pull_request_url)
class RepoEventSchema(RhodecodeEvent.MarshmallowSchema):
"""
Marshmallow schema for a repository event
"""
repository = fields.Nested(RepositorySchema)
class RepoEvent(RhodecodeEvent):
@ -26,7 +49,10 @@ class RepoEvent(RhodecodeEvent):
:param repo: a :class:`Repository` instance
"""
MarshmallowSchema = RepoEventSchema
def __init__(self, repo):
super(RepoEvent, self).__init__()
self.repo = repo
@ -73,6 +99,16 @@ class RepoVCSEvent(RepoEvent):
self.extras = extras
super(RepoVCSEvent, self).__init__(self.repo)
@property
def acting_user(self):
if self.extras.get('username'):
return User.get_by_username(extras['username'])
@property
def acting_ip(self):
if self.extras.get('ip'):
return User.get_by_username(extras['ip'])
class RepoPrePullEvent(RepoVCSEvent):
"""

View file

@ -17,7 +17,8 @@
# and proprietary license terms, please see https://rhodecode.com/licenses/
from zope.interface import implementer
from rhodecode.events import RhodecodeEvent
from rhodecode.events.base import RhodecodeEvent
from rhodecode.events.interfaces import (
IUserRegistered, IUserPreCreate, IUserPreUpdate)

View file

@ -1641,6 +1641,7 @@ class Repository(Base, BaseModel):
'repo_name': repo.repo_name,
'repo_type': repo.repo_type,
'clone_uri': repo.clone_uri or '',
'url': url('summary_home', repo_name=self.repo_name, qualified=True),
'private': repo.private,
'created_on': repo.created_on,
'description': repo.description,
@ -3112,10 +3113,9 @@ class PullRequest(Base, _PullRequestBase):
merge_status = PullRequestModel().merge_status(pull_request)
data = {
'pull_request_id': pull_request.pull_request_id,
'url': url('pullrequest_show',
repo_name=pull_request.target_repo.repo_name,
pull_request_id=pull_request.pull_request_id,
qualified=True),
'url': url('pullrequest_show', repo_name=self.target_repo.repo_name,
pull_request_id=self.pull_request_id,
qualified=True),
'title': pull_request.title,
'description': pull_request.description,
'status': pull_request.status,

View file

@ -748,6 +748,11 @@ class PullRequestModel(BaseModel):
return ids_to_add, ids_to_remove
def get_url(self, pull_request):
return url('pullrequest_show', repo_name=self.target_repo.repo_name,
pull_request_id=self.pull_request_id,
qualified=True)
def notify_reviewers(self, pull_request, reviewers_ids):
# notification to reviewers
if not reviewers_ids:

View file

@ -141,6 +141,9 @@ class RepoModel(BaseModel):
return None
def get_url(self, repo):
return url('summary_home', repo_name=repo.repo_name, qualified=True)
def get_users(self, name_contains=None, limit=20, only_active=True):
# TODO: mikhail: move this method to the UserModel.
query = self.sa.query(User)

View file

@ -78,6 +78,7 @@ requirements = [
'ipython',
'iso8601',
'kombu',
'marshmallow',
'msgpack-python',
'packaging',
'psycopg2',