Last active
April 18, 2020 09:55
-
-
Save sneppy/63ea892b7b18f8231f57d9211dacda74 to your computer and use it in GitHub Desktop.
PonyORM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--------------------------------------------- | |
-- This procedure takes as input the hash of | |
-- a post commit and returns the chain of | |
-- parent commits up to the root commit (i.e. | |
-- NULL parent) | |
--------------------------------------------- | |
-- Drop old procedure | |
drop procedure if exists commit_chain; | |
delimiter // | |
create procedure commit_chain(in commit_hash varchar(40)) deterministic | |
begin | |
declare current_hash varchar(40) default NULL; | |
declare post_id bigint(20) unsigned default NULL; | |
-- Create temporary table to store chain. | |
-- Init with initial commit. | |
drop temporary table if exists chain; | |
create temporary table chain select * from postcommit where hash = commit_hash; | |
-- Get current hash and global post id. | |
select post, parent | |
from chain | |
into post_id, current_hash; | |
while current_hash is not NULL do | |
insert into chain | |
select * | |
from postcommit | |
where hash = current_hash and post = post_id; -- Sanity check. | |
-- Update current hash. | |
select parent | |
from chain | |
where hash = current_hash | |
into current_hash; | |
end while; | |
select * | |
from chain; | |
-- Drop temporary table. | |
drop temporary table if exists chain; | |
end // | |
delimiter ; | |
-- Procedure created |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from datetime import datetime | |
from pony.orm import Database, db_session, select | |
from pony.orm import PrimaryKey, Required, Optional, Set, LongStr, Json | |
from hashlib import sha1 | |
db = Database() | |
class Post(db.Entity): | |
""" A post associated to either a party an adventure or both """ | |
# Post id, large int | |
id = PrimaryKey(int, unsigned=True, size=64, auto=True) | |
# Post title | |
title = Required(str, max_len=255, index=True) | |
# Set of commits | |
commits = Set('PostCommit') | |
# HEAD commit | |
head = Optional(str, max_len=40, nullable=True) | |
@property | |
def content(self): | |
""" Return computed content """ | |
return self.get_content_at() | |
def get_content_at(self, commit_hash=None): | |
""" Compute content starting from commit hash """ | |
commit_hash = commit_hash or self.head | |
if commit_hash is None: return '' | |
# Get commits. | |
commits = PostCommit.select_by_sql('call commit_chain($commit_hash)') | |
print(commits) | |
if len(commits) == 0: return '' | |
# Check that post id is correct. | |
if any([c.post.id != self.id for c in commits]): raise ValueError | |
# Get deltas. | |
deltas = [c.delta for c in commits] | |
if len(deltas) == 1: | |
return deltas[0] | |
else: | |
# Apply patches and return result. | |
patches = dmp.patch_fromText('\n'.join(deltas[1:])) | |
return dmp.patch_apply(patches, deltas[0])[0] | |
@property | |
def commit_head(self): | |
""" Return head commit """ | |
return PostCommit[self.head] | |
def __init__(self, *args, **kwargs): | |
""" Constructor """ | |
# Trim title | |
kwargs['title'] = kwargs['title'].strip() | |
super().__init__(*args, **kwargs) | |
class PostCommit(db.Entity): | |
""" A single commit associated with a post """ | |
# Commit hash, uniquely identifies commit | |
hash = PrimaryKey(str, max_len=40) | |
# Post associated with this commit | |
post = Required(Post, index=True) | |
# Commit delta content | |
delta = Required(LongStr) | |
# Parent commit hash | |
parent = Optional('PostCommit', nullable=True) | |
# Set of children commits | |
children = Set('PostCommit') | |
def __init__(self, *args, **kwargs): | |
""" We must compute hash and delta """ | |
if not kwargs['delta']: | |
# No real change, raise exception to abort | |
raise ValueError | |
# And compute hash | |
created_at = kwargs.get('created_at') or datetime.now() | |
kwargs['hash'] = sha1(':'.join([kwargs.get('parent', None) or '', kwargs['delta'], created_at.isoformat()]).encode('utf-8')).hexdigest() | |
# Create entity. | |
super().__init__(*args, **kwargs) | |
# If parent commit was HEAD, make this HEAD | |
if self.parent is None or self.post.head == self.parent.hash: | |
self.post.head = self.hash | |
@staticmethod | |
def commit_chain(commit): | |
""" Get chain of commits """ | |
# If PostCommit object try to get hash | |
commit_hash = getattr(commit, 'hash', commit) | |
return PostCommit.select_by_sql('call commit_chain($commit_hash)') | |
# Bind db | |
db.bind(provider='mysql', host='localhost', user='', passwd='', db='') | |
db.generate_mapping(create_tables=True) | |
with db_session: | |
post = select(p for p in Post).first() | |
commits = PostCommit.select_by_sql('call commit_chain($post.head)') | |
print(commits) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mysqlclient==1.4.6 | |
pkg-resources==0.0.0 | |
pony==0.7.13 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment