From d6ee451f88bc68678aed47b097ae709a81f64ad0 Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Fri, 5 Jun 2020 10:22:45 -0700 Subject: [PATCH] Use python modules to encode SQLAlchemy content schema instead of binaries. --- .../contentschema/versions/__init__.py | 0 .../versions/content_schema_1.py | 203 +++++++++++++++ .../versions/content_schema_2.py | 218 ++++++++++++++++ .../versions/content_schema_3.py | 202 +++++++++++++++ .../versions/content_schema_current.py | 236 ++++++++++++++++++ .../versions/content_schema_unversioned.py | 192 ++++++++++++++ .../versions/content_schema_v020beta1.py | 173 +++++++++++++ .../versions/content_schema_v040beta3.py | 188 ++++++++++++++ .../core/content/fixtures/1_content_schema | Bin 50583 -> 0 bytes .../core/content/fixtures/2_content_schema | Bin 54395 -> 0 bytes .../core/content/fixtures/3_content_schema | Bin 46018 -> 0 bytes .../content/fixtures/current_content_schema | Bin 50728 -> 0 bytes .../fixtures/unversioned_content_schema | Bin 47069 -> 0 bytes .../fixtures/v0.2.0-beta1_content_schema | Bin 40098 -> 0 bytes .../fixtures/v0.4.0-beta3_content_schema | Bin 46542 -> 0 bytes .../management/commands/generate_schema.py | 27 +- .../core/content/test/test_channel_import.py | 5 +- .../core/content/utils/sqlalchemybridge.py | 51 +++- requirements/dev.txt | 1 + 19 files changed, 1473 insertions(+), 23 deletions(-) create mode 100644 kolibri/core/content/contentschema/versions/__init__.py create mode 100644 kolibri/core/content/contentschema/versions/content_schema_1.py create mode 100644 kolibri/core/content/contentschema/versions/content_schema_2.py create mode 100644 kolibri/core/content/contentschema/versions/content_schema_3.py create mode 100644 kolibri/core/content/contentschema/versions/content_schema_current.py create mode 100644 kolibri/core/content/contentschema/versions/content_schema_unversioned.py create mode 100644 kolibri/core/content/contentschema/versions/content_schema_v020beta1.py create mode 100644 kolibri/core/content/contentschema/versions/content_schema_v040beta3.py delete mode 100644 kolibri/core/content/fixtures/1_content_schema delete mode 100644 kolibri/core/content/fixtures/2_content_schema delete mode 100644 kolibri/core/content/fixtures/3_content_schema delete mode 100644 kolibri/core/content/fixtures/current_content_schema delete mode 100644 kolibri/core/content/fixtures/unversioned_content_schema delete mode 100644 kolibri/core/content/fixtures/v0.2.0-beta1_content_schema delete mode 100644 kolibri/core/content/fixtures/v0.4.0-beta3_content_schema diff --git a/kolibri/core/content/contentschema/versions/__init__.py b/kolibri/core/content/contentschema/versions/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/kolibri/core/content/contentschema/versions/content_schema_1.py b/kolibri/core/content/contentschema/versions/content_schema_1.py new file mode 100644 index 00000000000..34f10952230 --- /dev/null +++ b/kolibri/core/content/contentschema/versions/content_schema_1.py @@ -0,0 +1,203 @@ +# coding: utf-8 +from sqlalchemy import Boolean +from sqlalchemy import CHAR +from sqlalchemy import Column +from sqlalchemy import Float +from sqlalchemy import ForeignKey +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +Base = declarative_base() +metadata = Base.metadata + + +class ContentContenttag(Base): + __tablename__ = "content_contenttag" + + id = Column(CHAR(32), primary_key=True) + tag_name = Column(String(30), nullable=False) + + +class ContentLanguage(Base): + __tablename__ = "content_language" + + id = Column(String(14), primary_key=True) + lang_code = Column(String(3), nullable=False, index=True) + lang_subcode = Column(String(10), index=True) + lang_name = Column(String(100)) + lang_direction = Column(String(3), nullable=False) + + +class ContentLocalfile(Base): + __tablename__ = "content_localfile" + + id = Column(String(32), primary_key=True) + extension = Column(String(40), nullable=False) + available = Column(Boolean, nullable=False) + file_size = Column(Integer) + + +class ContentContentnode(Base): + __tablename__ = "content_contentnode" + + id = Column(CHAR(32), primary_key=True) + title = Column(String(200), nullable=False) + content_id = Column(CHAR(32), nullable=False, index=True) + channel_id = Column(CHAR(32), nullable=False, index=True) + description = Column(String(400)) + sort_order = Column(Float) + license_owner = Column(String(200), nullable=False) + author = Column(String(200), nullable=False) + kind = Column(String(200), nullable=False) + available = Column(Boolean, nullable=False) + stemmed_metaphone = Column(String(1800), nullable=False) + lft = Column(Integer, nullable=False, index=True) + rght = Column(Integer, nullable=False, index=True) + tree_id = Column(Integer, nullable=False, index=True) + level = Column(Integer, nullable=False, index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + license_description = Column(String(400)) + license_name = Column(String(50)) + parent_id = Column(ForeignKey("content_contentnode.id"), index=True) + + lang = relationship("ContentLanguage") + parent = relationship("ContentContentnode", remote_side=[id]) + + +class ContentAssessmentmetadata(Base): + __tablename__ = "content_assessmentmetadata" + + id = Column(CHAR(32), primary_key=True) + assessment_item_ids = Column(Text, nullable=False) + number_of_assessments = Column(Integer, nullable=False) + mastery_model = Column(Text, nullable=False) + randomize = Column(Boolean, nullable=False) + is_manipulable = Column(Boolean, nullable=False) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + + +class ContentChannelmetadata(Base): + __tablename__ = "content_channelmetadata" + + id = Column(CHAR(32), primary_key=True) + name = Column(String(200), nullable=False) + description = Column(String(400), nullable=False) + author = Column(String(400), nullable=False) + version = Column(Integer, nullable=False) + thumbnail = Column(Text, nullable=False) + last_updated = Column(String) + min_schema_version = Column(String(50), nullable=False) + root_id = Column(ForeignKey("content_contentnode.id"), nullable=False, index=True) + + root = relationship("ContentContentnode") + + +class ContentContentnodeHasPrerequisite(Base): + __tablename__ = "content_contentnode_has_prerequisite" + __table_args__ = ( + Index( + "content_contentnode_has_prerequisite_from_contentnode_id_c9e1d527_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeRelated(Base): + __tablename__ = "content_contentnode_related" + __table_args__ = ( + Index( + "content_contentnode_related_from_contentnode_id_fc2ed20c_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeTags(Base): + __tablename__ = "content_contentnode_tags" + __table_args__ = ( + Index( + "content_contentnode_tags_contentnode_id_64a4ac15_uniq", + "contentnode_id", + "contenttag_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + contenttag_id = Column( + ForeignKey("content_contenttag.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + contenttag = relationship("ContentContenttag") + + +class ContentFile(Base): + __tablename__ = "content_file" + + id = Column(CHAR(32), primary_key=True) + available = Column(Boolean, nullable=False) + preset = Column(String(150), nullable=False) + supplementary = Column(Boolean, nullable=False) + thumbnail = Column(Boolean, nullable=False) + priority = Column(Integer, index=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + lang_id = Column(ForeignKey("content_language.id"), index=True) + local_file_id = Column( + ForeignKey("content_localfile.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + lang = relationship("ContentLanguage") + local_file = relationship("ContentLocalfile") diff --git a/kolibri/core/content/contentschema/versions/content_schema_2.py b/kolibri/core/content/contentschema/versions/content_schema_2.py new file mode 100644 index 00000000000..1ea8a3f1809 --- /dev/null +++ b/kolibri/core/content/contentschema/versions/content_schema_2.py @@ -0,0 +1,218 @@ +# coding: utf-8 +from sqlalchemy import Boolean +from sqlalchemy import CHAR +from sqlalchemy import Column +from sqlalchemy import Float +from sqlalchemy import ForeignKey +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +Base = declarative_base() +metadata = Base.metadata + + +class ContentContenttag(Base): + __tablename__ = "content_contenttag" + + id = Column(CHAR(32), primary_key=True) + tag_name = Column(String(30), nullable=False) + + +class ContentLanguage(Base): + __tablename__ = "content_language" + + id = Column(String(14), primary_key=True) + lang_code = Column(String(3), nullable=False, index=True) + lang_subcode = Column(String(10), index=True) + lang_name = Column(String(100)) + lang_direction = Column(String(3), nullable=False) + + +class ContentLocalfile(Base): + __tablename__ = "content_localfile" + + id = Column(String(32), primary_key=True) + extension = Column(String(40), nullable=False) + available = Column(Boolean, nullable=False) + file_size = Column(Integer) + + +class ContentContentnode(Base): + __tablename__ = "content_contentnode" + __table_args__ = ( + Index( + "content_contentnode_level_channel_id_kind_fd732cc4_idx", + "level", + "channel_id", + "kind", + ), + Index( + "content_contentnode_level_channel_id_available_29f0bb18_idx", + "level", + "channel_id", + "available", + ), + ) + + id = Column(CHAR(32), primary_key=True) + title = Column(String(200), nullable=False) + content_id = Column(CHAR(32), nullable=False, index=True) + channel_id = Column(CHAR(32), nullable=False, index=True) + description = Column(String(400)) + sort_order = Column(Float) + license_owner = Column(String(200), nullable=False) + author = Column(String(200), nullable=False) + kind = Column(String(200), nullable=False) + available = Column(Boolean, nullable=False) + stemmed_metaphone = Column(String(1800), nullable=False) + lft = Column(Integer, nullable=False, index=True) + rght = Column(Integer, nullable=False, index=True) + tree_id = Column(Integer, nullable=False, index=True) + level = Column(Integer, nullable=False, index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + license_description = Column(String(400)) + license_name = Column(String(50)) + coach_content = Column(Boolean, nullable=False) + parent_id = Column(ForeignKey("content_contentnode.id"), index=True) + + lang = relationship("ContentLanguage") + parent = relationship("ContentContentnode", remote_side=[id]) + + +class ContentAssessmentmetadata(Base): + __tablename__ = "content_assessmentmetadata" + + id = Column(CHAR(32), primary_key=True) + assessment_item_ids = Column(Text, nullable=False) + number_of_assessments = Column(Integer, nullable=False) + mastery_model = Column(Text, nullable=False) + randomize = Column(Boolean, nullable=False) + is_manipulable = Column(Boolean, nullable=False) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + + +class ContentChannelmetadata(Base): + __tablename__ = "content_channelmetadata" + + id = Column(CHAR(32), primary_key=True) + name = Column(String(200), nullable=False) + description = Column(String(400), nullable=False) + author = Column(String(400), nullable=False) + version = Column(Integer, nullable=False) + thumbnail = Column(Text, nullable=False) + last_updated = Column(String) + min_schema_version = Column(String(50), nullable=False) + root_id = Column(ForeignKey("content_contentnode.id"), nullable=False, index=True) + + root = relationship("ContentContentnode") + + +class ContentContentnodeHasPrerequisite(Base): + __tablename__ = "content_contentnode_has_prerequisite" + __table_args__ = ( + Index( + "content_contentnode_has_prerequisite_from_contentnode_id_to_contentnode_id_c9e1d527_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeRelated(Base): + __tablename__ = "content_contentnode_related" + __table_args__ = ( + Index( + "content_contentnode_related_from_contentnode_id_to_contentnode_id_fc2ed20c_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeTags(Base): + __tablename__ = "content_contentnode_tags" + __table_args__ = ( + Index( + "content_contentnode_tags_contentnode_id_contenttag_id_64a4ac15_uniq", + "contentnode_id", + "contenttag_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + contenttag_id = Column( + ForeignKey("content_contenttag.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + contenttag = relationship("ContentContenttag") + + +class ContentFile(Base): + __tablename__ = "content_file" + + id = Column(CHAR(32), primary_key=True) + available = Column(Boolean, nullable=False) + preset = Column(String(150), nullable=False) + supplementary = Column(Boolean, nullable=False) + thumbnail = Column(Boolean, nullable=False) + priority = Column(Integer, index=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + lang_id = Column(ForeignKey("content_language.id"), index=True) + local_file_id = Column( + ForeignKey("content_localfile.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + lang = relationship("ContentLanguage") + local_file = relationship("ContentLocalfile") diff --git a/kolibri/core/content/contentschema/versions/content_schema_3.py b/kolibri/core/content/contentschema/versions/content_schema_3.py new file mode 100644 index 00000000000..6a54e1ec685 --- /dev/null +++ b/kolibri/core/content/contentschema/versions/content_schema_3.py @@ -0,0 +1,202 @@ +# coding: utf-8 +from sqlalchemy import Boolean +from sqlalchemy import CHAR +from sqlalchemy import Column +from sqlalchemy import Float +from sqlalchemy import ForeignKey +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +Base = declarative_base() +metadata = Base.metadata + + +class ContentContenttag(Base): + __tablename__ = "content_contenttag" + + id = Column(CHAR(32), primary_key=True) + tag_name = Column(String(30), nullable=False) + + +class ContentLanguage(Base): + __tablename__ = "content_language" + + id = Column(String(14), primary_key=True) + lang_code = Column(String(3), nullable=False, index=True) + lang_subcode = Column(String(10), index=True) + lang_name = Column(String(100)) + lang_direction = Column(String(3), nullable=False) + + +class ContentLocalfile(Base): + __tablename__ = "content_localfile" + + id = Column(String(32), primary_key=True) + extension = Column(String(40), nullable=False) + available = Column(Boolean, nullable=False) + file_size = Column(Integer) + + +class ContentContentnode(Base): + __tablename__ = "content_contentnode" + + id = Column(CHAR(32), primary_key=True) + license_name = Column(String(50)) + license_description = Column(Text) + title = Column(String(200), nullable=False) + coach_content = Column(Boolean, nullable=False) + content_id = Column(CHAR(32), nullable=False, index=True) + channel_id = Column(CHAR(32), nullable=False, index=True) + description = Column(Text) + sort_order = Column(Float) + license_owner = Column(String(200), nullable=False) + author = Column(String(200), nullable=False) + kind = Column(String(200), nullable=False) + available = Column(Boolean, nullable=False) + lft = Column(Integer, nullable=False, index=True) + rght = Column(Integer, nullable=False, index=True) + tree_id = Column(Integer, nullable=False, index=True) + level = Column(Integer, nullable=False, index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + parent_id = Column(ForeignKey("content_contentnode.id"), index=True) + + lang = relationship("ContentLanguage") + parent = relationship("ContentContentnode", remote_side=[id]) + + +class ContentAssessmentmetadata(Base): + __tablename__ = "content_assessmentmetadata" + + id = Column(CHAR(32), primary_key=True) + assessment_item_ids = Column(Text, nullable=False) + number_of_assessments = Column(Integer, nullable=False) + mastery_model = Column(Text, nullable=False) + randomize = Column(Boolean, nullable=False) + is_manipulable = Column(Boolean, nullable=False) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + + +class ContentChannelmetadata(Base): + __tablename__ = "content_channelmetadata" + + id = Column(CHAR(32), primary_key=True) + name = Column(String(200), nullable=False) + description = Column(String(400), nullable=False) + author = Column(String(400), nullable=False) + version = Column(Integer, nullable=False) + thumbnail = Column(Text, nullable=False) + last_updated = Column(String) + min_schema_version = Column(String(50), nullable=False) + root_id = Column(ForeignKey("content_contentnode.id"), nullable=False, index=True) + + root = relationship("ContentContentnode") + + +class ContentContentnodeHasPrerequisite(Base): + __tablename__ = "content_contentnode_has_prerequisite" + __table_args__ = ( + Index( + "content_contentnode_has_prerequisite_from_contentnode_id_to_contentnode_id_c9e1d527_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeRelated(Base): + __tablename__ = "content_contentnode_related" + __table_args__ = ( + Index( + "content_contentnode_related_from_contentnode_id_to_contentnode_id_fc2ed20c_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeTags(Base): + __tablename__ = "content_contentnode_tags" + __table_args__ = ( + Index( + "content_contentnode_tags_contentnode_id_contenttag_id_64a4ac15_uniq", + "contentnode_id", + "contenttag_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + contenttag_id = Column( + ForeignKey("content_contenttag.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + contenttag = relationship("ContentContenttag") + + +class ContentFile(Base): + __tablename__ = "content_file" + + id = Column(CHAR(32), primary_key=True) + preset = Column(String(150), nullable=False) + supplementary = Column(Boolean, nullable=False) + thumbnail = Column(Boolean, nullable=False) + priority = Column(Integer, index=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + lang_id = Column(ForeignKey("content_language.id"), index=True) + local_file_id = Column( + ForeignKey("content_localfile.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + lang = relationship("ContentLanguage") + local_file = relationship("ContentLocalfile") diff --git a/kolibri/core/content/contentschema/versions/content_schema_current.py b/kolibri/core/content/contentschema/versions/content_schema_current.py new file mode 100644 index 00000000000..a39d3442e69 --- /dev/null +++ b/kolibri/core/content/contentschema/versions/content_schema_current.py @@ -0,0 +1,236 @@ +# coding: utf-8 +from sqlalchemy import BigInteger +from sqlalchemy import Boolean +from sqlalchemy import CHAR +from sqlalchemy import Column +from sqlalchemy import Float +from sqlalchemy import ForeignKey +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +Base = declarative_base() +metadata = Base.metadata + + +class ContentContenttag(Base): + __tablename__ = "content_contenttag" + + id = Column(CHAR(32), primary_key=True) + tag_name = Column(String(30), nullable=False) + + +class ContentLanguage(Base): + __tablename__ = "content_language" + + id = Column(String(14), primary_key=True) + lang_code = Column(String(3), nullable=False, index=True) + lang_subcode = Column(String(10), index=True) + lang_name = Column(String(100)) + lang_direction = Column(String(3), nullable=False) + + +class ContentLocalfile(Base): + __tablename__ = "content_localfile" + + id = Column(String(32), primary_key=True) + available = Column(Boolean, nullable=False) + file_size = Column(Integer) + extension = Column(String(40), nullable=False) + + +class ContentContentnode(Base): + __tablename__ = "content_contentnode" + __table_args__ = ( + Index( + "content_contentnode_level_channel_id_available_29f0bb18_idx", + "level", + "channel_id", + "available", + ), + Index( + "content_contentnode_level_channel_id_kind_fd732cc4_idx", + "level", + "channel_id", + "kind", + ), + ) + + id = Column(CHAR(32), primary_key=True) + title = Column(String(200), nullable=False) + content_id = Column(CHAR(32), nullable=False, index=True) + channel_id = Column(CHAR(32), nullable=False, index=True) + description = Column(Text) + sort_order = Column(Float) + license_owner = Column(String(200), nullable=False) + author = Column(String(200), nullable=False) + available = Column(Boolean, nullable=False) + lft = Column(Integer, nullable=False, index=True) + rght = Column(Integer, nullable=False, index=True) + tree_id = Column(Integer, nullable=False, index=True) + level = Column(Integer, nullable=False, index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + license_description = Column(Text) + license_name = Column(String(50)) + coach_content = Column(Boolean, nullable=False) + num_coach_contents = Column(Integer) + on_device_resources = Column(Integer) + kind = Column(String(200), nullable=False) + parent_id = Column(ForeignKey("content_contentnode.id"), index=True) + + lang = relationship("ContentLanguage") + parent = relationship("ContentContentnode", remote_side=[id]) + + +class ContentAssessmentmetadata(Base): + __tablename__ = "content_assessmentmetadata" + + id = Column(CHAR(32), primary_key=True) + assessment_item_ids = Column(Text, nullable=False) + number_of_assessments = Column(Integer, nullable=False) + mastery_model = Column(Text, nullable=False) + randomize = Column(Boolean, nullable=False) + is_manipulable = Column(Boolean, nullable=False) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + + +class ContentChannelmetadata(Base): + __tablename__ = "content_channelmetadata" + + id = Column(CHAR(32), primary_key=True) + name = Column(String(200), nullable=False) + description = Column(String(400), nullable=False) + author = Column(String(400), nullable=False) + version = Column(Integer, nullable=False) + thumbnail = Column(Text, nullable=False) + last_updated = Column(String) + min_schema_version = Column(String(50), nullable=False) + root_id = Column(ForeignKey("content_contentnode.id"), nullable=False, index=True) + published_size = Column(BigInteger) + total_resource_count = Column(Integer) + order = Column(Integer) + public = Column(Boolean) + + root = relationship("ContentContentnode") + + +class ContentContentnodeHasPrerequisite(Base): + __tablename__ = "content_contentnode_has_prerequisite" + __table_args__ = ( + Index( + "content_contentnode_has_prerequisite_from_contentnode_id_to_contentnode_id_c9e1d527_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeRelated(Base): + __tablename__ = "content_contentnode_related" + __table_args__ = ( + Index( + "content_contentnode_related_from_contentnode_id_to_contentnode_id_fc2ed20c_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeTags(Base): + __tablename__ = "content_contentnode_tags" + __table_args__ = ( + Index( + "content_contentnode_tags_contentnode_id_contenttag_id_64a4ac15_uniq", + "contentnode_id", + "contenttag_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + contenttag_id = Column( + ForeignKey("content_contenttag.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + contenttag = relationship("ContentContenttag") + + +class ContentFile(Base): + __tablename__ = "content_file" + + id = Column(CHAR(32), primary_key=True) + preset = Column(String(150), nullable=False) + supplementary = Column(Boolean, nullable=False) + thumbnail = Column(Boolean, nullable=False) + priority = Column(Integer, index=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + lang_id = Column(ForeignKey("content_language.id"), index=True) + local_file_id = Column( + ForeignKey("content_localfile.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + lang = relationship("ContentLanguage") + local_file = relationship("ContentLocalfile") + + +class ContentChannelmetadataIncludedLanguages(Base): + __tablename__ = "content_channelmetadata_included_languages" + + id = Column(Integer, primary_key=True) + channelmetadata_id = Column( + ForeignKey("content_channelmetadata.id"), nullable=False + ) + language_id = Column(ForeignKey("content_language.id"), nullable=False) + + channelmetadata = relationship("ContentChannelmetadata") + language = relationship("ContentLanguage") diff --git a/kolibri/core/content/contentschema/versions/content_schema_unversioned.py b/kolibri/core/content/contentschema/versions/content_schema_unversioned.py new file mode 100644 index 00000000000..7aa3fb200a9 --- /dev/null +++ b/kolibri/core/content/contentschema/versions/content_schema_unversioned.py @@ -0,0 +1,192 @@ +# coding: utf-8 +from sqlalchemy import Boolean +from sqlalchemy import CHAR +from sqlalchemy import Column +from sqlalchemy import Float +from sqlalchemy import ForeignKey +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +Base = declarative_base() +metadata = Base.metadata + + +class ContentChannelmetadata(Base): + __tablename__ = "content_channelmetadata" + + id = Column(CHAR(32), primary_key=True) + name = Column(String(200), nullable=False) + description = Column(String(400), nullable=False) + author = Column(String(400), nullable=False) + version = Column(Integer, nullable=False) + thumbnail = Column(Text, nullable=False) + root_pk = Column(CHAR(32), nullable=False) + + +class ContentContenttag(Base): + __tablename__ = "content_contenttag" + + id = Column(CHAR(32), primary_key=True) + tag_name = Column(String(30), nullable=False) + + +class ContentLanguage(Base): + __tablename__ = "content_language" + + id = Column(String(14), primary_key=True) + lang_code = Column(String(3), nullable=False, index=True) + lang_subcode = Column(String(10), index=True) + lang_name = Column(String(100)) + lang_direction = Column(String(3), nullable=False) + + +class ContentLicense(Base): + __tablename__ = "content_license" + + id = Column(Integer, primary_key=True) + license_name = Column(String(50), nullable=False) + license_description = Column(String(400)) + + +class ContentContentnode(Base): + __tablename__ = "content_contentnode" + + id = Column(CHAR(32), primary_key=True) + title = Column(String(200), nullable=False) + content_id = Column(CHAR(32), nullable=False, index=True) + description = Column(String(400)) + sort_order = Column(Float) + license_owner = Column(String(200), nullable=False) + author = Column(String(200), nullable=False) + kind = Column(String(200), nullable=False) + available = Column(Boolean, nullable=False) + stemmed_metaphone = Column(String(1800), nullable=False) + lft = Column(Integer, nullable=False, index=True) + rght = Column(Integer, nullable=False, index=True) + tree_id = Column(Integer, nullable=False, index=True) + level = Column(Integer, nullable=False, index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + license_id = Column(ForeignKey("content_license.id"), index=True) + parent_id = Column(ForeignKey("content_contentnode.id"), index=True) + + lang = relationship("ContentLanguage") + license = relationship("ContentLicense") + parent = relationship("ContentContentnode", remote_side=[id]) + + +class ContentAssessmentmetadata(Base): + __tablename__ = "content_assessmentmetadata" + + id = Column(CHAR(32), primary_key=True) + assessment_item_ids = Column(Text, nullable=False) + number_of_assessments = Column(Integer, nullable=False) + mastery_model = Column(Text, nullable=False) + randomize = Column(Boolean, nullable=False) + is_manipulable = Column(Boolean, nullable=False) + contentnode_id = Column(ForeignKey("content_contentnode.id"), index=True) + + contentnode = relationship("ContentContentnode") + + +class ContentContentnodeHasPrerequisite(Base): + __tablename__ = "content_contentnode_has_prerequisite" + __table_args__ = ( + Index( + "content_contentnode_has_prerequisite_from_contentnode_id_c9e1d527_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeRelated(Base): + __tablename__ = "content_contentnode_related" + __table_args__ = ( + Index( + "content_contentnode_related_from_contentnode_id_fc2ed20c_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeTags(Base): + __tablename__ = "content_contentnode_tags" + __table_args__ = ( + Index( + "content_contentnode_tags_contentnode_id_64a4ac15_uniq", + "contentnode_id", + "contenttag_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + contenttag_id = Column( + ForeignKey("content_contenttag.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + contenttag = relationship("ContentContenttag") + + +class ContentFile(Base): + __tablename__ = "content_file" + + id = Column(CHAR(32), primary_key=True) + checksum = Column(String(400), nullable=False) + extension = Column(String(40), nullable=False) + available = Column(Boolean, nullable=False) + file_size = Column(Integer) + preset = Column(String(150), nullable=False) + supplementary = Column(Boolean, nullable=False) + thumbnail = Column(Boolean, nullable=False) + priority = Column(Integer) + contentnode_id = Column(ForeignKey("content_contentnode.id"), index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + + contentnode = relationship("ContentContentnode") + lang = relationship("ContentLanguage") diff --git a/kolibri/core/content/contentschema/versions/content_schema_v020beta1.py b/kolibri/core/content/contentschema/versions/content_schema_v020beta1.py new file mode 100644 index 00000000000..d26c3aebb11 --- /dev/null +++ b/kolibri/core/content/contentschema/versions/content_schema_v020beta1.py @@ -0,0 +1,173 @@ +# coding: utf-8 +from sqlalchemy import Boolean +from sqlalchemy import CHAR +from sqlalchemy import Column +from sqlalchemy import Float +from sqlalchemy import ForeignKey +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +Base = declarative_base() +metadata = Base.metadata + + +class ContentChannelmetadata(Base): + __tablename__ = "content_channelmetadata" + + id = Column(CHAR(32), primary_key=True) + name = Column(String(200), nullable=False) + description = Column(String(400), nullable=False) + author = Column(String(400), nullable=False) + version = Column(Integer, nullable=False) + thumbnail = Column(Text, nullable=False) + root_pk = Column(CHAR(32), nullable=False) + + +class ContentContenttag(Base): + __tablename__ = "content_contenttag" + + id = Column(CHAR(32), primary_key=True) + tag_name = Column(String(30), nullable=False) + + +class ContentLanguage(Base): + __tablename__ = "content_language" + + id = Column(String(7), primary_key=True) + lang_code = Column(String(3), nullable=False, index=True) + lang_subcode = Column(String(3), index=True) + + +class ContentLicense(Base): + __tablename__ = "content_license" + + id = Column(Integer, primary_key=True) + license_name = Column(String(50), nullable=False) + + +class ContentContentnode(Base): + __tablename__ = "content_contentnode" + + id = Column(CHAR(32), primary_key=True) + title = Column(String(200), nullable=False) + content_id = Column(CHAR(32), nullable=False) + description = Column(String(400)) + sort_order = Column(Float) + license_owner = Column(String(200), nullable=False) + author = Column(String(200), nullable=False) + kind = Column(String(200), nullable=False) + available = Column(Boolean, nullable=False) + lft = Column(Integer, nullable=False, index=True) + rght = Column(Integer, nullable=False, index=True) + tree_id = Column(Integer, nullable=False, index=True) + level = Column(Integer, nullable=False, index=True) + license_id = Column(ForeignKey("content_license.id"), index=True) + stemmed_metaphone = Column(String(1800), nullable=False) + parent_id = Column(ForeignKey("content_contentnode.id"), index=True) + + license = relationship("ContentLicense") + parent = relationship("ContentContentnode", remote_side=[id]) + + +class ContentContentnodeHasPrerequisite(Base): + __tablename__ = "content_contentnode_has_prerequisite" + __table_args__ = ( + Index( + "content_contentnode_has_prerequisite_from_contentnode_id_c9e1d527_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeRelated(Base): + __tablename__ = "content_contentnode_related" + __table_args__ = ( + Index( + "content_contentnode_related_from_contentnode_id_fc2ed20c_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeTags(Base): + __tablename__ = "content_contentnode_tags" + __table_args__ = ( + Index( + "content_contentnode_tags_contentnode_id_64a4ac15_uniq", + "contentnode_id", + "contenttag_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + contenttag_id = Column( + ForeignKey("content_contenttag.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + contenttag = relationship("ContentContenttag") + + +class ContentFile(Base): + __tablename__ = "content_file" + + id = Column(CHAR(32), primary_key=True) + checksum = Column(String(400), nullable=False) + extension = Column(String(40), nullable=False) + available = Column(Boolean, nullable=False) + file_size = Column(Integer) + supplementary = Column(Boolean, nullable=False) + thumbnail = Column(Boolean, nullable=False) + priority = Column(Integer) + contentnode_id = Column(ForeignKey("content_contentnode.id"), index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + preset = Column(String(150), nullable=False) + + contentnode = relationship("ContentContentnode") + lang = relationship("ContentLanguage") diff --git a/kolibri/core/content/contentschema/versions/content_schema_v040beta3.py b/kolibri/core/content/contentschema/versions/content_schema_v040beta3.py new file mode 100644 index 00000000000..012547799a4 --- /dev/null +++ b/kolibri/core/content/contentschema/versions/content_schema_v040beta3.py @@ -0,0 +1,188 @@ +# coding: utf-8 +from sqlalchemy import Boolean +from sqlalchemy import CHAR +from sqlalchemy import Column +from sqlalchemy import Float +from sqlalchemy import ForeignKey +from sqlalchemy import Index +from sqlalchemy import Integer +from sqlalchemy import String +from sqlalchemy import Text +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import relationship + +Base = declarative_base() +metadata = Base.metadata + + +class ContentChannelmetadata(Base): + __tablename__ = "content_channelmetadata" + + id = Column(CHAR(32), primary_key=True) + name = Column(String(200), nullable=False) + description = Column(String(400), nullable=False) + author = Column(String(400), nullable=False) + version = Column(Integer, nullable=False) + thumbnail = Column(Text, nullable=False) + root_pk = Column(CHAR(32), nullable=False) + + +class ContentContenttag(Base): + __tablename__ = "content_contenttag" + + id = Column(CHAR(32), primary_key=True) + tag_name = Column(String(30), nullable=False) + + +class ContentLanguage(Base): + __tablename__ = "content_language" + + id = Column(String(7), primary_key=True) + lang_code = Column(String(3), nullable=False, index=True) + lang_subcode = Column(String(3), index=True) + + +class ContentLicense(Base): + __tablename__ = "content_license" + + id = Column(Integer, primary_key=True) + license_name = Column(String(50), nullable=False) + license_description = Column(String(400)) + + +class ContentContentnode(Base): + __tablename__ = "content_contentnode" + + id = Column(CHAR(32), primary_key=True) + title = Column(String(200), nullable=False) + content_id = Column(CHAR(32), nullable=False, index=True) + description = Column(String(400)) + sort_order = Column(Float) + license_owner = Column(String(200), nullable=False) + author = Column(String(200), nullable=False) + kind = Column(String(200), nullable=False) + available = Column(Boolean, nullable=False) + stemmed_metaphone = Column(String(1800), nullable=False) + lft = Column(Integer, nullable=False, index=True) + rght = Column(Integer, nullable=False, index=True) + tree_id = Column(Integer, nullable=False, index=True) + level = Column(Integer, nullable=False, index=True) + license_id = Column(ForeignKey("content_license.id"), index=True) + parent_id = Column(ForeignKey("content_contentnode.id"), index=True) + + license = relationship("ContentLicense") + parent = relationship("ContentContentnode", remote_side=[id]) + + +class ContentAssessmentmetadata(Base): + __tablename__ = "content_assessmentmetadata" + + id = Column(CHAR(32), primary_key=True) + assessment_item_ids = Column(Text, nullable=False) + number_of_assessments = Column(Integer, nullable=False) + mastery_model = Column(Text, nullable=False) + randomize = Column(Boolean, nullable=False) + is_manipulable = Column(Boolean, nullable=False) + contentnode_id = Column(ForeignKey("content_contentnode.id"), index=True) + + contentnode = relationship("ContentContentnode") + + +class ContentContentnodeHasPrerequisite(Base): + __tablename__ = "content_contentnode_has_prerequisite" + __table_args__ = ( + Index( + "content_contentnode_has_prerequisite_from_contentnode_id_c9e1d527_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeHasPrerequisite.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeRelated(Base): + __tablename__ = "content_contentnode_related" + __table_args__ = ( + Index( + "content_contentnode_related_from_contentnode_id_fc2ed20c_uniq", + "from_contentnode_id", + "to_contentnode_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + from_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + to_contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + + from_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.from_contentnode_id == ContentContentnode.id", + ) + to_contentnode = relationship( + "ContentContentnode", + primaryjoin="ContentContentnodeRelated.to_contentnode_id == ContentContentnode.id", + ) + + +class ContentContentnodeTags(Base): + __tablename__ = "content_contentnode_tags" + __table_args__ = ( + Index( + "content_contentnode_tags_contentnode_id_64a4ac15_uniq", + "contentnode_id", + "contenttag_id", + unique=True, + ), + ) + + id = Column(Integer, primary_key=True) + contentnode_id = Column( + ForeignKey("content_contentnode.id"), nullable=False, index=True + ) + contenttag_id = Column( + ForeignKey("content_contenttag.id"), nullable=False, index=True + ) + + contentnode = relationship("ContentContentnode") + contenttag = relationship("ContentContenttag") + + +class ContentFile(Base): + __tablename__ = "content_file" + + id = Column(CHAR(32), primary_key=True) + checksum = Column(String(400), nullable=False) + extension = Column(String(40), nullable=False) + available = Column(Boolean, nullable=False) + file_size = Column(Integer) + preset = Column(String(150), nullable=False) + supplementary = Column(Boolean, nullable=False) + thumbnail = Column(Boolean, nullable=False) + priority = Column(Integer) + contentnode_id = Column(ForeignKey("content_contentnode.id"), index=True) + lang_id = Column(ForeignKey("content_language.id"), index=True) + + contentnode = relationship("ContentContentnode") + lang = relationship("ContentLanguage") diff --git a/kolibri/core/content/fixtures/1_content_schema b/kolibri/core/content/fixtures/1_content_schema deleted file mode 100644 index 94ff91848f96ea869b10526533334651c960ae5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50583 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%0A6sO6cb_8SrM@04I{m75hU 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 EAH9u1BLDyZ diff --git a/kolibri/core/content/fixtures/3_content_schema b/kolibri/core/content/fixtures/3_content_schema deleted file mode 100644 index 47d2a9baf1e548205fa7781a73a0ae25eb191cbf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46018 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 diff --git a/kolibri/core/content/fixtures/current_content_schema b/kolibri/core/content/fixtures/current_content_schema deleted file mode 100644 index 726d0fe52626ca959d48af40bd8b7901711127d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50728 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 Cs)H2( diff --git a/kolibri/core/content/fixtures/unversioned_content_schema b/kolibri/core/content/fixtures/unversioned_content_schema deleted file mode 100644 index d233238b99393712a15c91cdbc119a871a37cf57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47069 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 diff --git a/kolibri/core/content/fixtures/v0.2.0-beta1_content_schema b/kolibri/core/content/fixtures/v0.2.0-beta1_content_schema deleted file mode 100644 index c7141d3f5f69e91a7f2907d9af803450936b9ff1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40098 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 z z#+Js~3N+IgjHh54x=mVY8bd5Wg(a}3#!yXiftrSvs8xm$#x#cGus#LVG)5}PN^GVv zw#YO_5y=-B!D7=GWAd>kZ{IYwHpVu_=*%>>HAZ9_<1Ep3Dl*g1Fh6k(@)Or!`(5zw znZ~eT6=RYvIG)Vtf;(Ey6EtV*g6d0m!Pqn=BIkGEz_45z=IjvU>=10fTz}6rh7B8C zc$)1(W|V7J%Xv4=*~+E9bh!$qp$(Lm$;RJZ`DxRbf`G*{7@3APGp1pkM@>Tsd6^1w zFbQHB+Om9B1Z-m(jtbj14b4bRgBjRfc=@=aa_t6(&fYt?!I6O!$lf4hxpy)|zW1r? z3CaiMAQK4fE8H>O*z`&zDLnT_LhMW>1P)5PJ4 z+WwaO0MM><%)rBIdK%A_jw*G-D;)>n<;^@5L<@8i)Pm6hT?>*d(8JrPb;ijWhdJg< zW9V&Enr=z40ofo@QZNi&tw%%bnU@7DRmA5wxwv+wkzi-JlK?*YZvLA@O@ucNp_d zjS7dYyG(F57!6xm)MVJIm^`qFhNm8d4gJTEu+j&YwW0q69A44``D!Gn*8emv z7OTHd*7noI&k%_*J!>hRQ>NPM^LRKz1w(rs^>^*H?LT;tO!x;c;W+X#h_$x!3FTKb zCbZR8@fO+YYX|~)9W+~g0}t=%fr+hJ!PB<-Cb6E@g3kDs@!wYd0MD3atM8;J?;7Pj zrIgyLX2M2*5k62tiLF|dVq5)C32Lh!;R)npu*g<5v&dFIF~+CHD7Dqkkb0Vh+3M#S z(sHM4^$UW0I|am6HLJF^`jt_>1|wVj2CwB~is7fj38S9xa2)v_R9pQ)Nv62OR)0jq z5*##J{RxjFKZ9*-^%rCQs!^e>{$_&T!N^v%s3}`rf7!PBhh_06Xtw$n9!I+HWx&W* zm&5yaY;}1}(z&g6g%aCpH~b5wyC!PiR(lZTNKX)3?OCwZUPxG+gN5Ddwg+!z#B-zz z@}){p?X)j0^U;1L>tcY0O49O0^9 ziCJ7~cY1ZCp%vz34g6eoRY|-%y%vFFcY19Cfvlq<-HBXRiPnc~|F)ygu9wb;tCCL& zuSW)ycK{AQz6VB6je&UiL2@wO*WJ)48-d}z?sU3Gv}?Vw3d2$q_H{Qw$m$o2jAAoo zsc{*#Rmurt6oYX1H3Lu^VGAWiM!{6Smd!?Nd`qN(Yz11a2dgL5NLKfq{_eop&iti{ zUnUw_H*(nM@D0!*Cr@SV^#^_ z8=zy2dy48tAKv^FAA+>5wjoT1-4=&)T~Kwk9d7zR*ak$TvF(WqWCvwvKN*iFoEQB6 z`bqLl<{ilZl}x~KWFi=;WD;K91_Wc3>}-@>z&0w`RfRS?Nxcoa8^S;)gOM_JS5`_F zQwY;fDsdc{3ToZ=P?BX8tu6PoXh)-M|9>xhOyO?vLCD>1EF(33`TF@%qn_33=T~h~9{p@h;YXtXLdZqd6^A5(g2ow`tz`!{w{2*%t0_i8o}^q-91ki z`LlsmX|lMv8aD+&wWn{sd-}>dAAhkp(K!1Gfw#M!GfV+mC1-KXVDuwZ`oOkkjlRJh mz6;xrJhLtQ8WQ)|=TzsUg#`LD#Pe`@O%UWYL9nG}@c#j#+ewN5 diff --git a/kolibri/core/content/fixtures/v0.4.0-beta3_content_schema b/kolibri/core/content/fixtures/v0.4.0-beta3_content_schema deleted file mode 100644 index 2449e8f27ed36ef77fb094f644ae701b4ae07ef8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46542 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 BQnmm9 diff --git a/kolibri/core/content/management/commands/generate_schema.py b/kolibri/core/content/management/commands/generate_schema.py index 35faf8972a2..197100a6be7 100644 --- a/kolibri/core/content/management/commands/generate_schema.py +++ b/kolibri/core/content/management/commands/generate_schema.py @@ -1,7 +1,6 @@ import io import json import os -import pickle import shutil import sys from collections import defaultdict @@ -12,17 +11,21 @@ from django.core.management import call_command from django.core.management.base import BaseCommand from django.db import connections +from sqlacodegen.codegen import CodeGenerator from sqlalchemy import create_engine from sqlalchemy import MetaData -from sqlalchemy.ext.automap import automap_base from sqlalchemy.orm import sessionmaker from kolibri.core.content.apps import KolibriContentConfig from kolibri.core.content.constants.schema_versions import CONTENT_SCHEMA_VERSION from kolibri.core.content.constants.schema_versions import CURRENT_SCHEMA_VERSION +from kolibri.core.content.utils.sqlalchemybridge import ( + coerce_version_name_to_valid_module_path, +) from kolibri.core.content.utils.sqlalchemybridge import get_default_db_string -from kolibri.core.content.utils.sqlalchemybridge import SCHEMA_PATH_TEMPLATE +from kolibri.core.content.utils.sqlalchemybridge import prepare_base from kolibri.core.content.utils.sqlalchemybridge import SharingPool +from kolibri.core.content.utils.sqlalchemybridge import SQLALCHEMY_CLASSES_PATH_TEMPLATE DATA_PATH_TEMPLATE = os.path.join( os.path.dirname(__file__), "../../fixtures/{name}_content_data.json" @@ -93,13 +96,23 @@ def handle(self, *args, **options): if name != "channelmetadatacache" ] metadata.reflect(bind=engine, only=table_names) - Base = automap_base(metadata=metadata) + Base = prepare_base(metadata, name=version) # TODO map relationship backreferences using the django names - Base.prepare() session = sessionmaker(bind=engine, autoflush=False)() - with open(SCHEMA_PATH_TEMPLATE.format(name=version), "wb") as f: - pickle.dump(metadata, f, protocol=2) + metadata.bind = engine + + generator = CodeGenerator( + metadata, False, False, True, True, False, nocomments=False + ) + + with io.open( + SQLALCHEMY_CLASSES_PATH_TEMPLATE.format( + name=coerce_version_name_to_valid_module_path(version) + ), + "w", + ) as f: + generator.render(f) # Only do this if we are generating a new export schema version if not no_export_schema: diff --git a/kolibri/core/content/test/test_channel_import.py b/kolibri/core/content/test/test_channel_import.py index d4dad535881..f3266b6576e 100644 --- a/kolibri/core/content/test/test_channel_import.py +++ b/kolibri/core/content/test/test_channel_import.py @@ -1,7 +1,6 @@ import io import json import os -import pickle import tempfile import uuid @@ -36,6 +35,7 @@ from kolibri.core.content.utils.channel_import import ChannelImport from kolibri.core.content.utils.channel_import import import_channel_from_local_db from kolibri.core.content.utils.sqlalchemybridge import get_default_db_string +from kolibri.core.content.utils.sqlalchemybridge import load_metadata @patch("kolibri.core.content.utils.channel_import.Bridge") @@ -404,8 +404,7 @@ def set_content_fixture(self, db_path_mock): "sqlite:///" + self.content_db_path, convert_unicode=True ) - with open(SCHEMA_PATH_TEMPLATE.format(name=self.schema_name), "rb") as f: - metadata = pickle.load(f) + metadata = load_metadata(self.schema_name) data_path = DATA_PATH_TEMPLATE.format(name=self.data_name) with io.open(data_path, mode="r", encoding="utf-8") as f: diff --git a/kolibri/core/content/utils/sqlalchemybridge.py b/kolibri/core/content/utils/sqlalchemybridge.py index 1a859eb8d1c..7078eb0f0bd 100644 --- a/kolibri/core/content/utils/sqlalchemybridge.py +++ b/kolibri/core/content/utils/sqlalchemybridge.py @@ -1,6 +1,6 @@ +import importlib import logging import os -import pickle from django.apps import apps from django.conf import settings @@ -176,21 +176,46 @@ def set_all_class_defaults(Base): pass -SCHEMA_PATH_TEMPLATE = os.path.join( - os.path.dirname(__file__), "../fixtures/{name}_content_schema" +__SQLALCHEMY_CLASSES_PATH = ( + "contentschema", + "versions", ) +__SQLALCHEMY_CLASSES_MODULE_NAME = "content_schema_{name}" -def prepare_bases(): +SQLALCHEMY_CLASSES_PATH_TEMPLATE = os.path.join( + os.path.dirname(__file__), + "..", + *(__SQLALCHEMY_CLASSES_PATH + (__SQLALCHEMY_CLASSES_MODULE_NAME + ".py",)) +) + +SQLALCHEMY_CLASSES_MODULE_PATH_TEMPLATE = ".".join( + tuple(__name__.split(".")[:-2]) + + __SQLALCHEMY_CLASSES_PATH + + (__SQLALCHEMY_CLASSES_MODULE_NAME,) +) + + +def coerce_version_name_to_valid_module_path(name): + # Only required to support the legacy schema versions that + # use Kolibri versions explicitly in their name. + return name.replace(".", "").replace("-", "") - for name in CONTENT_DB_SCHEMA_VERSIONS + [CURRENT_SCHEMA_VERSION]: - with open(SCHEMA_PATH_TEMPLATE.format(name=name), "rb") as f: - metadata = pickle.load(f) - cascade_relationships = name == CURRENT_SCHEMA_VERSION - BASES[name] = prepare_base( - metadata, cascade_relationships=cascade_relationships +def load_metadata(name): + module = importlib.import_module( + SQLALCHEMY_CLASSES_MODULE_PATH_TEMPLATE.format( + name=coerce_version_name_to_valid_module_path(name) ) + ) + return module.Base.metadata + + +def prepare_bases(): + + for name in CONTENT_DB_SCHEMA_VERSIONS + [CURRENT_SCHEMA_VERSION]: + metadata = load_metadata(name) + BASES[name] = prepare_base(metadata, name=name) def get_model_from_cls(cls): @@ -208,13 +233,13 @@ def get_field_from_model_by_column(model, column): return next((f for f in model._meta.fields if f.column == column), None) -def prepare_base(metadata, cascade_relationships=False): +def prepare_base(metadata, name=None): """ Create a Base mapping for models for a particular schema version of the content app A Base mapping defines the mapping from database tables to the SQLAlchemy ORM and is our main entrypoint for interacting with content databases and the content app tables of the default database. - If cascade_relationships is True, then also attempt to use Django model information + If name is CURRENT_SCHEMA_VERSION, then also attempt to use Django model information to setup proper relationship cascade behaviour to allow deletion in SQLAlchemy. """ # Set up the base mapping using the automap_base method, using the metadata passed in @@ -232,7 +257,7 @@ def _gen_relationship( base, direction, return_fn, attrname, local_cls, referred_cls, **kw ) - if cascade_relationships: + if name == CURRENT_SCHEMA_VERSION: Base.prepare(generate_relationship=_gen_relationship) else: Base.prepare() diff --git a/requirements/dev.txt b/requirements/dev.txt index 2f772752b24..74c01057bb2 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -11,3 +11,4 @@ tabulate==0.8.2 fonttools==3.29.0 nodeenv==1.3.3 click==7.0 +sqlacodegen==2.1.0