# HG changeset patch # User Mads Kiilerich # Date 2020-10-30 14:54:42 # Node ID c98c7d4c9ec362e7f89a0f3a7b35613332a60928 # Parent 905cab5f971d63426b3789101aff55602d2f8d5a model: changes toward import whole modules *If* there should be circular dependencies, importing 'from' another module could fail because the module at that time only was partially imported. That had to be worked around by importing at runtime instead of globally. Instead, try to always import whole modules. (But we should still try to avoid cycles.) diff --git a/kallithea/model/comment.py b/kallithea/model/comment.py --- a/kallithea/model/comment.py +++ b/kallithea/model/comment.py @@ -33,8 +33,7 @@ from tg.i18n import ugettext as _ from kallithea.lib import webutils from kallithea.lib.utils import extract_mentioned_users from kallithea.lib.utils2 import shorter -from kallithea.model import db, meta -from kallithea.model.notification import NotificationModel +from kallithea.model import db, meta, notification log = logging.getLogger(__name__) @@ -69,7 +68,7 @@ class ChangesetCommentsModel(object): # changeset if revision: - notification_type = NotificationModel.TYPE_CHANGESET_COMMENT + notification_type = notification.NotificationModel.TYPE_CHANGESET_COMMENT cs = repo.scm_instance.get_changeset(revision) desc = cs.short_id @@ -114,7 +113,7 @@ class ChangesetCommentsModel(object): } # pull request elif pull_request: - notification_type = NotificationModel.TYPE_PULL_REQUEST_COMMENT + notification_type = notification.NotificationModel.TYPE_PULL_REQUEST_COMMENT desc = comment.pull_request.title _org_ref_type, org_ref_name, _org_rev = comment.pull_request.org_ref.split(':') _other_ref_type, other_ref_name, _other_rev = comment.pull_request.other_ref.split(':') @@ -208,7 +207,7 @@ class ChangesetCommentsModel(object): closing_pr=closing_pr) email_kwargs['is_mention'] = False # create notification objects, and emails - NotificationModel().create( + notification.NotificationModel().create( created_by=author, subject=subj, body=body, recipients=recipients, type_=notification_type, email_kwargs=email_kwargs, @@ -219,7 +218,7 @@ class ChangesetCommentsModel(object): email_kwargs['is_mention'] = True subj = _('[Mention]') + ' ' + subj # FIXME: this subject is wrong and unused! - NotificationModel().create( + notification.NotificationModel().create( created_by=author, subject=subj, body=body, recipients=mention_recipients, type_=notification_type, diff --git a/kallithea/model/gist.py b/kallithea/model/gist.py --- a/kallithea/model/gist.py +++ b/kallithea/model/gist.py @@ -34,9 +34,7 @@ import traceback from kallithea.lib import ext_json from kallithea.lib.utils2 import AttributeDict, ascii_bytes, safe_int, time_to_datetime -from kallithea.model import db, meta -from kallithea.model.repo import RepoModel -from kallithea.model.scm import ScmModel +from kallithea.model import db, meta, repo, scm log = logging.getLogger(__name__) @@ -58,12 +56,12 @@ class GistModel(object): :param gist: gist object """ - root_path = RepoModel().repos_path + root_path = repo.RepoModel().repos_path rm_path = os.path.join(root_path, db.Gist.GIST_STORE_LOC, gist.gist_access_id) log.info("Removing %s", rm_path) shutil.rmtree(rm_path) - def _store_metadata(self, repo, gist_id, gist_access_id, user_id, gist_type, + def _store_metadata(self, fs_repo, gist_id, gist_access_id, user_id, gist_type, gist_expires): """ store metadata inside the gist, this can be later used for imports @@ -78,7 +76,7 @@ class GistModel(object): 'gist_expires': gist_expires, 'gist_updated': time.time(), } - with open(os.path.join(repo.path, '.hg', db.Gist.GIST_METADATA_FILE), 'wb') as f: + with open(os.path.join(fs_repo.path, '.hg', db.Gist.GIST_METADATA_FILE), 'wb') as f: f.write(ascii_bytes(ext_json.dumps(metadata))) def get_gist(self, gist): @@ -90,8 +88,8 @@ class GistModel(object): :param gist_access_id: """ - repo = db.Gist.get_by_access_id(gist_access_id) - cs = repo.scm_instance.get_changeset(revision) + gist_repo = db.Gist.get_by_access_id(gist_access_id) + cs = gist_repo.scm_instance.get_changeset(revision) return cs, [n for n in cs.get_node('/')] def create(self, description, owner, ip_addr, gist_mapping, @@ -125,7 +123,7 @@ class GistModel(object): gist.gist_access_id = str(gist.gist_id) log.debug('Creating new %s GIST repo %s', gist_type, gist.gist_access_id) - repo = RepoModel()._create_filesystem_repo( + fs_repo = repo.RepoModel()._create_filesystem_repo( repo_name=gist.gist_access_id, repo_type='hg', repo_group=db.Gist.GIST_STORE_LOC) processed_mapping = {} @@ -151,9 +149,9 @@ class GistModel(object): # fake Kallithea Repository object fake_repo = AttributeDict(dict( repo_name=os.path.join(db.Gist.GIST_STORE_LOC, gist.gist_access_id), - scm_instance_no_cache=lambda: repo, + scm_instance_no_cache=lambda: fs_repo, )) - ScmModel().create_nodes( + scm.ScmModel().create_nodes( user=owner.user_id, ip_addr=ip_addr, repo=fake_repo, @@ -162,7 +160,7 @@ class GistModel(object): trigger_push_hook=False ) - self._store_metadata(repo, gist.gist_id, gist.gist_access_id, + self._store_metadata(fs_repo, gist.gist_id, gist.gist_access_id, owner.user_id, gist.gist_type, gist.gist_expires) return gist @@ -221,7 +219,7 @@ class GistModel(object): self._store_metadata(gist_repo, gist.gist_id, gist.gist_access_id, owner.user_id, gist.gist_type, gist.gist_expires) - ScmModel().update_nodes( + scm.ScmModel().update_nodes( user=owner.user_id, ip_addr=ip_addr, repo=fake_repo, diff --git a/kallithea/model/pull_request.py b/kallithea/model/pull_request.py --- a/kallithea/model/pull_request.py +++ b/kallithea/model/pull_request.py @@ -36,8 +36,7 @@ from kallithea.lib import auth, webutils from kallithea.lib.hooks import log_create_pullrequest from kallithea.lib.utils import extract_mentioned_users from kallithea.lib.utils2 import ascii_bytes, short_ref_name, shorter -from kallithea.model import db, meta -from kallithea.model.notification import NotificationModel +from kallithea.model import changeset_status, comment, db, meta, notification log = logging.getLogger(__name__) @@ -114,18 +113,18 @@ class PullRequestModel(object): 'is_mention': False, } if reviewers: - NotificationModel().create(created_by=user, subject=subject, body=body, + notification.NotificationModel().create(created_by=user, subject=subject, body=body, recipients=reviewers, - type_=NotificationModel.TYPE_PULL_REQUEST, + type_=notification.NotificationModel.TYPE_PULL_REQUEST, email_kwargs=email_kwargs) if mention_recipients: email_kwargs['is_mention'] = True subject = _('[Mention]') + ' ' + subject # FIXME: this subject is wrong and unused! - NotificationModel().create(created_by=user, subject=subject, body=body, + notification.NotificationModel().create(created_by=user, subject=subject, body=body, recipients=mention_recipients, - type_=NotificationModel.TYPE_PULL_REQUEST, + type_=notification.NotificationModel.TYPE_PULL_REQUEST, email_kwargs=email_kwargs) return reviewers, redundant_reviewers @@ -272,9 +271,7 @@ class CreatePullRequestAction(object): self.org_repo.scm_instance._repo[b"refs/pull/%d/head" % pr.pull_request_id] = ascii_bytes(self.org_rev) # reset state to under-review - from kallithea.model.changeset_status import ChangesetStatusModel - from kallithea.model.comment import ChangesetCommentsModel - comment = ChangesetCommentsModel().create( + new_comment = comment.ChangesetCommentsModel().create( text='', repo=self.org_repo, author=created_by, @@ -282,11 +279,11 @@ class CreatePullRequestAction(object): send_email=False, status_change=db.ChangesetStatus.STATUS_UNDER_REVIEW, ) - ChangesetStatusModel().set_status( + changeset_status.ChangesetStatusModel().set_status( self.org_repo, db.ChangesetStatus.STATUS_UNDER_REVIEW, created_by, - comment, + new_comment, pull_request=pr, ) @@ -393,8 +390,7 @@ class CreatePullRequestIterationAction(o pull_request = self.create_action.execute() # Close old iteration - from kallithea.model.comment import ChangesetCommentsModel - ChangesetCommentsModel().create( + comment.ChangesetCommentsModel().create( text=_('Closed, next iteration: %s .') % pull_request.url(canonical=True), repo=self.old_pull_request.other_repo_id, author=request.authuser.user_id, diff --git a/kallithea/model/repo.py b/kallithea/model/repo.py --- a/kallithea/model/repo.py +++ b/kallithea/model/repo.py @@ -39,7 +39,7 @@ from kallithea.lib.hooks import log_dele from kallithea.lib.utils import is_valid_repo_uri, make_ui from kallithea.lib.utils2 import LazyProperty, get_current_authuser, obfuscate_url_pw, remove_prefix from kallithea.lib.vcs.backends import get_backend -from kallithea.model import db, meta +from kallithea.model import db, meta, scm log = logging.getLogger(__name__) @@ -131,7 +131,6 @@ class RepoModel(object): from tg import tmpl_context as c import kallithea.lib.helpers as h - from kallithea.model.scm import ScmModel def repo_lnk(name, rtype, rstate, private, fork_of): return _render('repo_name', name, rtype, rstate, private, fork_of, @@ -187,7 +186,7 @@ class RepoModel(object): repo.repo_state, repo.private, repo.fork), "following": following( repo.repo_id, - ScmModel().is_following_repo(repo.repo_name, request.authuser.user_id), + scm.ScmModel().is_following_repo(repo.repo_name, request.authuser.user_id), ), "last_change_iso": repo.last_db_change.isoformat(), "last_change": last_change(repo.last_db_change), @@ -332,8 +331,6 @@ class RepoModel(object): executed by create() repo, with exception of importing existing repos. """ - from kallithea.model.scm import ScmModel - owner = db.User.guess_instance(owner) fork_of = db.Repository.guess_instance(fork_of) repo_group = db.RepoGroup.guess_instance(repo_group) @@ -408,7 +405,7 @@ class RepoModel(object): self._create_default_perms(new_repo, private) # now automatically start following this repository as owner - ScmModel().toggle_following_repo(new_repo.repo_id, owner.user_id) + scm.ScmModel().toggle_following_repo(new_repo.repo_id, owner.user_id) # we need to flush here, in order to check if database won't # throw any exceptions, create filesystem dirs at the very end meta.Session().flush() @@ -628,7 +625,6 @@ class RepoModel(object): Note: clone_uri is low level and not validated - it might be a file system path used for validated cloning """ from kallithea.lib.utils import is_valid_repo, is_valid_repo_group - from kallithea.model.scm import ScmModel if '/' in repo_name: raise ValueError('repo_name must not contain groups got `%s`' % repo_name) @@ -669,7 +665,7 @@ class RepoModel(object): elif repo_type == 'git': repo = backend(repo_path, create=True, src_url=clone_uri, bare=True) # add kallithea hook into this repo - ScmModel().install_git_hooks(repo) + scm.ScmModel().install_git_hooks(repo) else: raise Exception('Not supported repo_type %s expected hg/git' % repo_type) diff --git a/kallithea/model/repo_group.py b/kallithea/model/repo_group.py --- a/kallithea/model/repo_group.py +++ b/kallithea/model/repo_group.py @@ -34,7 +34,7 @@ import traceback import kallithea.lib.utils2 from kallithea.lib.utils2 import LazyProperty -from kallithea.model import db, meta +from kallithea.model import db, meta, repo log = logging.getLogger(__name__) @@ -189,7 +189,6 @@ class RepoGroupModel(object): perms_updates=None, recursive=None, check_perms=True): from kallithea.lib.auth import HasUserGroupPermissionLevel - from kallithea.model.repo import RepoModel if not perms_new: perms_new = [] @@ -210,7 +209,7 @@ class RepoGroupModel(object): # we set group permission but we have to switch to repo # permission perm = perm.replace('group.', 'repository.') - RepoModel().grant_user_permission( + repo.RepoModel().grant_user_permission( repo=obj, user=user, perm=perm ) @@ -223,7 +222,7 @@ class RepoGroupModel(object): # we set group permission but we have to switch to repo # permission perm = perm.replace('group.', 'repository.') - RepoModel().grant_user_group_permission( + repo.RepoModel().grant_user_group_permission( repo=obj, group_name=users_group, perm=perm ) @@ -335,7 +334,6 @@ class RepoGroupModel(object): raise def add_permission(self, repo_group, obj, obj_type, perm, recursive): - from kallithea.model.repo import RepoModel repo_group = db.RepoGroup.guess_instance(repo_group) perm = db.Permission.guess_instance(perm) @@ -367,9 +365,9 @@ class RepoGroupModel(object): # for repos we need to hotfix the name of permission _perm = perm.permission_name.replace('group.', 'repository.') if obj_type == 'user': - RepoModel().grant_user_permission(el, user=obj, perm=_perm) + repo.RepoModel().grant_user_permission(el, user=obj, perm=_perm) elif obj_type == 'user_group': - RepoModel().grant_user_group_permission(el, group_name=obj, perm=_perm) + repo.RepoModel().grant_user_group_permission(el, group_name=obj, perm=_perm) else: raise Exception('undefined object type %s' % obj_type) else: @@ -391,7 +389,6 @@ class RepoGroupModel(object): :param obj_type: user or user group type :param recursive: recurse to all children of group """ - from kallithea.model.repo import RepoModel repo_group = db.RepoGroup.guess_instance(repo_group) for el in repo_group.recursive_groups_and_repos(): @@ -420,9 +417,9 @@ class RepoGroupModel(object): raise Exception('undefined object type %s' % obj_type) elif isinstance(el, db.Repository): if obj_type == 'user': - RepoModel().revoke_user_permission(el, user=obj) + repo.RepoModel().revoke_user_permission(el, user=obj) elif obj_type == 'user_group': - RepoModel().revoke_user_group_permission(el, group_name=obj) + repo.RepoModel().revoke_user_group_permission(el, group_name=obj) else: raise Exception('undefined object type %s' % obj_type) else: diff --git a/kallithea/model/user.py b/kallithea/model/user.py --- a/kallithea/model/user.py +++ b/kallithea/model/user.py @@ -166,7 +166,7 @@ class UserModel(object): raise def create_registration(self, form_data): - from kallithea.model.notification import NotificationModel + from kallithea.model import notification form_data['admin'] = False form_data['extern_type'] = db.User.DEFAULT_AUTH_TYPE @@ -188,9 +188,9 @@ class UserModel(object): 'new_username': new_user.username, 'new_email': new_user.email, 'new_full_name': new_user.full_name} - NotificationModel().create(created_by=new_user, subject=subject, + notification.NotificationModel().create(created_by=new_user, subject=subject, body=body, recipients=None, - type_=NotificationModel.TYPE_REGISTRATION, + type_=notification.NotificationModel.TYPE_REGISTRATION, email_kwargs=email_kwargs) def update(self, user_id, form_data, skip_attrs=None): @@ -315,7 +315,7 @@ class UserModel(object): email. """ from kallithea.lib.celerylib import tasks - from kallithea.model.notification import EmailNotificationModel + from kallithea.model import notification user_email = data['email'] user = db.User.get_by_email(user_email) @@ -336,13 +336,13 @@ class UserModel(object): else: log.debug('password reset user %s found but was managed', user) token = link = None - reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET - body = EmailNotificationModel().get_email_tmpl( + reg_type = notification.EmailNotificationModel.TYPE_PASSWORD_RESET + body = notification.EmailNotificationModel().get_email_tmpl( reg_type, 'txt', user=user.short_contact, reset_token=token, reset_url=link) - html_body = EmailNotificationModel().get_email_tmpl( + html_body = notification.EmailNotificationModel().get_email_tmpl( reg_type, 'html', user=user.short_contact, reset_token=token,