| |
@@ -33,40 +33,16 @@
|
| |
import bleach
|
| |
import sqlalchemy as sa
|
| |
|
| |
- from alembic import command as alembic_command
|
| |
- from alembic.config import Config as AlembicConfig
|
| |
- from sqlalchemy import create_engine
|
| |
- from sqlalchemy.ext.declarative import declarative_base
|
| |
- from sqlalchemy.orm import sessionmaker
|
| |
- from sqlalchemy.orm import scoped_session
|
| |
from sqlalchemy.orm import relation
|
| |
from sqlalchemy.orm import backref
|
| |
from sqlalchemy.orm.session import object_session
|
| |
|
| |
- import fedmsg
|
| |
- import fedmsg.utils
|
| |
-
|
| |
import hubs.defaults
|
| |
import hubs.widgets
|
| |
from hubs.authz import ObjectAuthzMixin, AccessLevel
|
| |
+ from hubs.database import BASE, Session
|
| |
from hubs.utils import username2avatar
|
| |
|
| |
-
|
| |
- class HubsBase(object):
|
| |
- def notify(self, username, changed):
|
| |
- obj = type(self).__name__.lower()
|
| |
- topic = obj + ".update"
|
| |
- fedmsg.publish(
|
| |
- topic=topic,
|
| |
- msg=dict(
|
| |
- username=username,
|
| |
- changed=changed,
|
| |
- )
|
| |
- )
|
| |
-
|
| |
-
|
| |
- BASE = declarative_base(cls=HubsBase)
|
| |
-
|
| |
log = logging.getLogger(__name__)
|
| |
|
| |
|
| |
@@ -77,35 +53,6 @@
|
| |
return location + choice
|
| |
|
| |
|
| |
- def init(db_url, debug=False, create=False):
|
| |
- """ Create the tables in the database using the information from the
|
| |
- url obtained.
|
| |
-
|
| |
- :arg db_url, URL used to connect to the database. The URL contains
|
| |
- information with regards to the database engine, the host to
|
| |
- connect to, the user and password and the database name.
|
| |
- ie: <engine>://<user>:<password>@<host>/<dbname>
|
| |
- :kwarg debug, a boolean specifying whether we should have the verbose
|
| |
- output of sqlalchemy or not.
|
| |
- :return a session that can be used to query the database.
|
| |
-
|
| |
- """
|
| |
- engine = create_engine(db_url, echo=debug)
|
| |
- if engine.name == "sqlite":
|
| |
- engine.execute("PRAGMA foreign_keys=ON")
|
| |
-
|
| |
- if create:
|
| |
- BASE.metadata.create_all(engine)
|
| |
- # Stamp the database with the lastest Alembic revision:
|
| |
- # http://alembic.zzzcomputing.com/en/latest/cookbook.html#building-an-up-to-date-database-from-scratch
|
| |
- alembic_cfg = AlembicConfig()
|
| |
- alembic_cfg.set_main_option("script_location", "hubs:migrations")
|
| |
- alembic_command.stamp(alembic_cfg, "head")
|
| |
- session = scoped_session(sessionmaker(bind=engine))
|
| |
- BASE.query = session.query_property()
|
| |
- return session
|
| |
-
|
| |
-
|
| |
ROLES = ['subscriber', 'member', 'owner', 'stargazer']
|
| |
|
| |
|
| |
@@ -172,15 +119,6 @@
|
| |
if idle > limit:
|
| |
return name
|
| |
|
| |
- @classmethod
|
| |
- def get_or_create(cls, session, name, summary, **extra):
|
| |
- self = cls.by_name(name)
|
| |
- if not self:
|
| |
- self = cls.create_group_hub(session, name, summary, **extra)
|
| |
- session.add(self)
|
| |
- session.commit()
|
| |
- return self
|
| |
-
|
| |
@property
|
| |
def owners(self):
|
| |
return [assoc.user for assoc in self.associations
|
| |
@@ -246,21 +184,23 @@
|
| |
return cls.query.filter_by(user_hub=True).all()
|
| |
|
| |
@classmethod
|
| |
- def create_user_hub(cls, session, username, fullname):
|
| |
+ def create_user_hub(cls, username, fullname):
|
| |
+ session = Session()
|
| |
hub = cls(name=username, user_hub=True)
|
| |
session.add(hub)
|
| |
hub_config = HubConfig(
|
| |
hub=hub, summary=fullname, avatar=username2avatar(username))
|
| |
session.add(hub_config)
|
| |
|
| |
- hubs.defaults.add_user_widgets(session, hub, username, fullname)
|
| |
+ hubs.defaults.add_user_widgets(hub, username, fullname)
|
| |
|
| |
- user = User.by_username(username)
|
| |
+ user = User.query.get(username)
|
| |
hub.subscribe(user, role='owner')
|
| |
return hub
|
| |
|
| |
@classmethod
|
| |
- def create_group_hub(cls, session, name, summary, **extra):
|
| |
+ def create_group_hub(cls, name, summary, **extra):
|
| |
+ session = Session()
|
| |
hub = cls(name=name, user_hub=False)
|
| |
session.add(hub)
|
| |
# TODO -- do something else, smarter for group avatars
|
| |
@@ -268,7 +208,7 @@
|
| |
hub=hub, summary=summary, avatar=username2avatar(name))
|
| |
session.add(hub_config)
|
| |
|
| |
- hubs.defaults.add_group_widgets(session, hub, name, summary, **extra)
|
| |
+ hubs.defaults.add_group_widgets(hub, name, summary, **extra)
|
| |
return hub
|
| |
|
| |
def _get_auth_user_access_level(self, user):
|
| |
@@ -577,18 +517,21 @@
|
| |
return cls.query.all()
|
| |
|
| |
@classmethod
|
| |
- def get_or_create(cls, session, username, fullname):
|
| |
+ def get_or_create(cls, username, fullname):
|
| |
if not username:
|
| |
raise ValueError("Must provide an username, not %r" % username)
|
| |
+ self = cls.query.get(username)
|
| |
+ if self is None:
|
| |
+ self = cls.create(username, fullname)
|
| |
+ return self
|
| |
|
| |
- self = cls.by_username(username)
|
| |
- if not self:
|
| |
- self = cls(username=username, fullname=fullname)
|
| |
- session.add(self)
|
| |
- if not Hub.by_name(self.username):
|
| |
- Hub.create_user_hub(session, self.username, self.fullname)
|
| |
-
|
| |
- session.commit()
|
| |
+ @classmethod
|
| |
+ def create(cls, username, fullname):
|
| |
+ session = Session()
|
| |
+ self = cls(username=username, fullname=fullname)
|
| |
+ session.add(self)
|
| |
+ if Hub.query.get(username) is None:
|
| |
+ Hub.create_user_hub(username, fullname)
|
| |
return self
|
| |
|
| |
|
| |
@@ -617,38 +560,29 @@
|
| |
username=username, visited_hub=visited_hub).first()
|
| |
|
| |
@classmethod
|
| |
- def increment_visits(cls, session, username, visited_hub):
|
| |
- row = cls.get_or_create(session, username=username,
|
| |
+ def increment_visits(cls, username, visited_hub):
|
| |
+ row = cls.get_or_create(username=username,
|
| |
visited_hub=visited_hub)
|
| |
row.count += 1
|
| |
- session.commit()
|
| |
|
| |
@classmethod
|
| |
- def _does_hub_exist(cls, session, hub=''):
|
| |
- return session.query(Hub).filter_by(name=hub).first() is not None
|
| |
-
|
| |
- @classmethod
|
| |
- def _does_user_exist(cls, session, user=''):
|
| |
- return session.query(User).filter_by(username=user).first() is not None
|
| |
-
|
| |
- @classmethod
|
| |
- def get_or_create(cls, session, username, visited_hub):
|
| |
+ def get_or_create(cls, username, visited_hub):
|
| |
if not username:
|
| |
raise ValueError("Must provide an username, not %r" % username)
|
| |
-
|
| |
if not visited_hub:
|
| |
raise ValueError("Must provide an hub, not %r" % visited_hub)
|
| |
-
|
| |
- if not cls._does_hub_exist(session, hub=visited_hub) \
|
| |
- or not cls._does_user_exist(session, user=username):
|
| |
+ hub_exists = Hub.query.get(visited_hub) is not None
|
| |
+ user_exists = User.query.get(username) is not None
|
| |
+ if not hub_exists or not user_exists:
|
| |
raise ValueError("Must provide a hub/user that exists")
|
| |
|
| |
- self = cls.get_visits_by_username_hub(username=username,
|
| |
- visited_hub=visited_hub)
|
| |
- if not self:
|
| |
+ self = cls.query.filter_by(
|
| |
+ username=username, visited_hub=visited_hub).first()
|
| |
+ if self is None:
|
| |
+ session = Session()
|
| |
self = cls(username=username, visited_hub=visited_hub)
|
| |
session.add(self)
|
| |
- session.commit()
|
| |
+ session.flush()
|
| |
return self
|
| |
|
| |
|
| |
This brings the usage closer to what SQLAlchemy docs recommend.
It also avoids some import loops, and passing the session around all the
time when outside of Flask's request context.
See:
- http://docs.sqlalchemy.org/en/latest/orm/contextual.html#unitofwork-contextual
- http://docs.sqlalchemy.org/en/latest/orm/session_basics.html#adding-additional-configuration-to-an-existing-sessionmaker