events: add serialization .to_dict() to events based on marshmallow
This commit is contained in:
parent
a0af559a3d
commit
23d7a947f5
13 changed files with 177 additions and 19 deletions
|
|
@ -831,6 +831,19 @@
|
||||||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
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 {
|
mccabe = super.buildPythonPackage {
|
||||||
name = "mccabe-0.3";
|
name = "mccabe-0.3";
|
||||||
buildInputs = with self; [];
|
buildInputs = with self; [];
|
||||||
|
|
@ -1355,7 +1368,7 @@
|
||||||
name = "rhodecode-enterprise-ce-4.3.0";
|
name = "rhodecode-enterprise-ce-4.3.0";
|
||||||
buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner];
|
buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner];
|
||||||
doCheck = true;
|
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 = ./.;
|
src = ./.;
|
||||||
meta = {
|
meta = {
|
||||||
license = [ { fullName = "AGPLv3, and Commercial License"; } ];
|
license = [ { fullName = "AGPLv3, and Commercial License"; } ];
|
||||||
|
|
@ -1637,5 +1650,5 @@
|
||||||
|
|
||||||
### Test requirements
|
### Test requirements
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,7 @@ iso8601==0.1.11
|
||||||
itsdangerous==0.24
|
itsdangerous==0.24
|
||||||
kombu==1.5.1
|
kombu==1.5.1
|
||||||
lxml==3.4.4
|
lxml==3.4.4
|
||||||
|
marshmallow==2.8.0
|
||||||
mccabe==0.3
|
mccabe==0.3
|
||||||
meld3==1.0.2
|
meld3==1.0.2
|
||||||
mock==1.0.1
|
mock==1.0.1
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,14 @@ class TestApiUpdateRepo(object):
|
||||||
({'enable_statistics': True}, SAME_AS_UPDATES),
|
({'enable_statistics': True}, SAME_AS_UPDATES),
|
||||||
({'enable_locking': True}, SAME_AS_UPDATES),
|
({'enable_locking': True}, SAME_AS_UPDATES),
|
||||||
({'enable_downloads': True}, SAME_AS_UPDATES),
|
({'enable_downloads': True}, SAME_AS_UPDATES),
|
||||||
({'name': 'new_repo_name'}, {'repo_name': 'new_repo_name'}),
|
({'name': 'new_repo_name'}, {
|
||||||
({'group': 'test_group_for_update'},
|
'repo_name': 'new_repo_name',
|
||||||
{'repo_name': 'test_group_for_update/%s' % UPDATE_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):
|
def test_api_update_repo(self, updates, expected, backend):
|
||||||
repo_name = UPDATE_REPO_NAME
|
repo_name = UPDATE_REPO_NAME
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,7 @@ class PullrequestsController(BaseRepoController):
|
||||||
h.flash(_('Successfully opened new pull request'),
|
h.flash(_('Successfully opened new pull request'),
|
||||||
category='success')
|
category='success')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
raise
|
||||||
msg = _('Error occurred during sending pull request')
|
msg = _('Error occurred during sending pull request')
|
||||||
log.exception(msg)
|
log.exception(msg)
|
||||||
h.flash(msg, category='error')
|
h.flash(msg, category='error')
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,6 @@
|
||||||
from pyramid.threadlocal import get_current_registry
|
from pyramid.threadlocal import get_current_registry
|
||||||
|
|
||||||
|
|
||||||
class RhodecodeEvent(object):
|
|
||||||
"""
|
|
||||||
Base event class for all Rhodecode events
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def trigger(event):
|
def trigger(event):
|
||||||
"""
|
"""
|
||||||
Helper method to send an event. This wraps the pyramid logic to send an
|
Helper method to send an event. This wraps the pyramid logic to send an
|
||||||
|
|
@ -37,6 +31,8 @@ def trigger(event):
|
||||||
registry.notify(event)
|
registry.notify(event)
|
||||||
|
|
||||||
|
|
||||||
|
from rhodecode.events.base import RhodecodeEvent
|
||||||
|
|
||||||
from rhodecode.events.user import (
|
from rhodecode.events.user import (
|
||||||
UserPreCreate,
|
UserPreCreate,
|
||||||
UserPreUpdate,
|
UserPreUpdate,
|
||||||
|
|
@ -44,6 +40,7 @@ from rhodecode.events.user import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from rhodecode.events.repo import (
|
from rhodecode.events.repo import (
|
||||||
|
RepoEvent,
|
||||||
RepoPreCreateEvent, RepoCreatedEvent,
|
RepoPreCreateEvent, RepoCreatedEvent,
|
||||||
RepoPreDeleteEvent, RepoDeletedEvent,
|
RepoPreDeleteEvent, RepoDeletedEvent,
|
||||||
RepoPrePushEvent, RepoPushEvent,
|
RepoPrePushEvent, RepoPushEvent,
|
||||||
|
|
@ -51,6 +48,7 @@ from rhodecode.events.repo import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from rhodecode.events.pullrequest import (
|
from rhodecode.events.pullrequest import (
|
||||||
|
PullRequestEvent,
|
||||||
PullRequestCreateEvent,
|
PullRequestCreateEvent,
|
||||||
PullRequestUpdateEvent,
|
PullRequestUpdateEvent,
|
||||||
PullRequestReviewEvent,
|
PullRequestReviewEvent,
|
||||||
|
|
|
||||||
69
rhodecode/events/base.py
Normal file
69
rhodecode/events/base.py
Normal 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
|
||||||
|
|
@ -16,15 +16,40 @@
|
||||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||||
|
|
||||||
|
from marshmallow import Schema, fields
|
||||||
|
|
||||||
from rhodecode.events.repo import RepoEvent
|
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):
|
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):
|
def __init__(self, pullrequest):
|
||||||
super(PullRequestEvent, self).__init__(pullrequest.target_repo)
|
super(PullRequestEvent, self).__init__(pullrequest.target_repo)
|
||||||
self.pullrequest = pullrequest
|
self.pullrequest = pullrequest
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,31 @@
|
||||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||||
|
|
||||||
|
from marshmallow import Schema, fields
|
||||||
|
|
||||||
from rhodecode.model.db import Repository, Session
|
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):
|
class RepoEvent(RhodecodeEvent):
|
||||||
|
|
@ -26,7 +49,10 @@ class RepoEvent(RhodecodeEvent):
|
||||||
|
|
||||||
:param repo: a :class:`Repository` instance
|
:param repo: a :class:`Repository` instance
|
||||||
"""
|
"""
|
||||||
|
MarshmallowSchema = RepoEventSchema
|
||||||
|
|
||||||
def __init__(self, repo):
|
def __init__(self, repo):
|
||||||
|
super(RepoEvent, self).__init__()
|
||||||
self.repo = repo
|
self.repo = repo
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -73,6 +99,16 @@ class RepoVCSEvent(RepoEvent):
|
||||||
self.extras = extras
|
self.extras = extras
|
||||||
super(RepoVCSEvent, self).__init__(self.repo)
|
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):
|
class RepoPrePullEvent(RepoVCSEvent):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@
|
||||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||||
|
|
||||||
from zope.interface import implementer
|
from zope.interface import implementer
|
||||||
from rhodecode.events import RhodecodeEvent
|
|
||||||
|
from rhodecode.events.base import RhodecodeEvent
|
||||||
from rhodecode.events.interfaces import (
|
from rhodecode.events.interfaces import (
|
||||||
IUserRegistered, IUserPreCreate, IUserPreUpdate)
|
IUserRegistered, IUserPreCreate, IUserPreUpdate)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1641,6 +1641,7 @@ class Repository(Base, BaseModel):
|
||||||
'repo_name': repo.repo_name,
|
'repo_name': repo.repo_name,
|
||||||
'repo_type': repo.repo_type,
|
'repo_type': repo.repo_type,
|
||||||
'clone_uri': repo.clone_uri or '',
|
'clone_uri': repo.clone_uri or '',
|
||||||
|
'url': url('summary_home', repo_name=self.repo_name, qualified=True),
|
||||||
'private': repo.private,
|
'private': repo.private,
|
||||||
'created_on': repo.created_on,
|
'created_on': repo.created_on,
|
||||||
'description': repo.description,
|
'description': repo.description,
|
||||||
|
|
@ -3112,10 +3113,9 @@ class PullRequest(Base, _PullRequestBase):
|
||||||
merge_status = PullRequestModel().merge_status(pull_request)
|
merge_status = PullRequestModel().merge_status(pull_request)
|
||||||
data = {
|
data = {
|
||||||
'pull_request_id': pull_request.pull_request_id,
|
'pull_request_id': pull_request.pull_request_id,
|
||||||
'url': url('pullrequest_show',
|
'url': url('pullrequest_show', repo_name=self.target_repo.repo_name,
|
||||||
repo_name=pull_request.target_repo.repo_name,
|
pull_request_id=self.pull_request_id,
|
||||||
pull_request_id=pull_request.pull_request_id,
|
qualified=True),
|
||||||
qualified=True),
|
|
||||||
'title': pull_request.title,
|
'title': pull_request.title,
|
||||||
'description': pull_request.description,
|
'description': pull_request.description,
|
||||||
'status': pull_request.status,
|
'status': pull_request.status,
|
||||||
|
|
|
||||||
|
|
@ -748,6 +748,11 @@ class PullRequestModel(BaseModel):
|
||||||
|
|
||||||
return ids_to_add, ids_to_remove
|
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):
|
def notify_reviewers(self, pull_request, reviewers_ids):
|
||||||
# notification to reviewers
|
# notification to reviewers
|
||||||
if not reviewers_ids:
|
if not reviewers_ids:
|
||||||
|
|
|
||||||
|
|
@ -141,6 +141,9 @@ class RepoModel(BaseModel):
|
||||||
|
|
||||||
return None
|
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):
|
def get_users(self, name_contains=None, limit=20, only_active=True):
|
||||||
# TODO: mikhail: move this method to the UserModel.
|
# TODO: mikhail: move this method to the UserModel.
|
||||||
query = self.sa.query(User)
|
query = self.sa.query(User)
|
||||||
|
|
|
||||||
1
setup.py
1
setup.py
|
|
@ -78,6 +78,7 @@ requirements = [
|
||||||
'ipython',
|
'ipython',
|
||||||
'iso8601',
|
'iso8601',
|
||||||
'kombu',
|
'kombu',
|
||||||
|
'marshmallow',
|
||||||
'msgpack-python',
|
'msgpack-python',
|
||||||
'packaging',
|
'packaging',
|
||||||
'psycopg2',
|
'psycopg2',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue