Commit afede34d authored by Gerion Entrup's avatar Gerion Entrup
Browse files

add mbdata subset

parent eb6ae0f2
Copyright (c) 2013 Lukas Lalinsky
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
MusicBrainz Database Tools
==========================
SQLAlchemy Models
-----------------
These is a flattened version of the MusicBrainz Database Tools from Lukáš Lalinský.
See https://bitbucket.org/lalinsky/mbdata for the original.
The code is modified to run with Python 3.
If you are developing a Python application that needs access to the MusicBrainz
data, you can use the `mbdata.models` module to get [SQLAlchemy](http://www.sqlalchemy.org/)
models mapped to the MusicBrainz database tables.
All tables from the MusicBrainz database are mapped, all foreign keys have one-way
relationships set up and some models, where it's essential to access their
related models, have two-way relationships (collections) set up.
In order to work with the relationships efficiently, you should use the appropriate
kind of [eager loading](http://docs.sqlalchemy.org/en/rel_0_8/orm/loading.html).
Example:
#!python
>>> from sqlalchemy import create_engine
>>> from sqlalchemy.orm import sessionmaker
>>> from mbdata.models import Artist
>>> engine = create_engine('postgresql://musicbrainz:musicbrainz@127.0.0.1/musicbrainz', echo=True)
>>> Session = sessionmaker(bind=engine)
>>> session = Session()
>>> artist = session.query(Artist).filter_by(gid='b10bbbfc-cf9e-42e0-be17-e2c3e1d2600d').first()
>>> print artist.name
This diff is collapsed.
# Copyright (C) 2013 Lukas Lalinsky
# Distributed under the MIT license, see the LICENSE file for details.
import re
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.dialects.postgres import UUID
from sqlalchemy.types import UserDefinedType
from sqlalchemy.sql.expression import ClauseElement, TextClause
@compiles(UUID, 'sqlite')
def visit_uuid_sqlite(element, compiler, **kwargs):
return 'CHAR(32)'
class regexp(ClauseElement):
def __init__(self, column, pattern):
self.column = column
self.pattern = TextClause(pattern)
@compiles(regexp)
def visit_regexp(element, compiler, **kwargs):
return '{0} REGEXP {1}'.format(
compiler.process(element.column),
compiler.process(element.pattern))
@compiles(regexp, 'postgresql')
def visit_regexp_postgresql(element, compiler, **kwargs):
return '{0} ~ {1}'.format(
compiler.process(element.column),
compiler.process(element.pattern))
class PartialDate(object):
__slots__ = ('year', 'month', 'day')
def __init__(self, year=None, month=None, day=None):
self.year = year
self.month = month
self.day = day
def __composite_values__(self):
return self.year, self.month, self.day
def __iter__(self):
yield self.year
yield self.month
yield self.day
def __repr__(self):
return "{0.__class__.__name__}(year={0.year}, month={0.month}, day={0.day})".format(self)
def __eq__(self, other):
return isinstance(other, PartialDate) and \
other.year == self.year and \
other.month == self.month and \
other.day == self.day
def __ne__(self, other):
return not self.__eq__(other)
def __bool__(self):
return bool(self.year or self.month or self.day)
class Point(UserDefinedType):
# pylint: disable=W0223
# pylint: disable=R0201
def get_col_spec(self):
return 'POINT'
def bind_processor(self, dialect):
def process(value):
if value is None:
return None
return '({0},{1})'.format(value[0], value[1])
return process
def result_processor(self, dialect, coltype):
def process(value):
if value is None:
return None
match = re.match(r'\((-?[0-9.]+),(-?[0-9.]+)\)', value)
return tuple([float(x) for x in match.groups()])
return process
class Cube(UserDefinedType):
# pylint: disable=W0223
# pylint: disable=R0201
def get_col_spec(self):
return 'CUBE'
def bind_processor(self, dialect):
def process(value):
if value is None:
return None
return value
return process
def result_processor(self, dialect, coltype):
def process(value):
if value is None:
return None
return value
return process
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment