Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@ idea:
cp -r scripts/idea/* .idea

elastic-docker:
docker run -d -v lbryhub:/usr/share/elasticsearch/data -p 9200:9200 -p 9300:9300 -e"ES_JAVA_OPTS=-Xms512m -Xmx512m" -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.12.1
docker run -d --env network.publish_host=127.0.0.1 -v lbryhub:/usr/share/elasticsearch/data -p 9200:9200 -p 9300:9300 -e"ES_JAVA_OPTS=-Xms512m -Xmx512m" -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.12.1
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seem to have to use this to get "make elastic-docker" to work. Is it just me? (MacOS aarch64)

13 changes: 12 additions & 1 deletion lbry/extras/daemon/daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -3735,7 +3735,18 @@ async def jsonrpc_stream_update(
if old_txo.claim.is_stream:
claim.stream.update(file_path=file_path, **kwargs)
elif old_txo.claim.is_repost:
claim.repost.update(**kwargs)
reposted_txo = await self.ledger.get_claim_by_claim_id(
old_txo.claim.repost.reference.claim_id, include_is_my_output=True
)
assert reposted_txo
#log.error("%s", reposted_txo)
assert isinstance(reposted_txo, Output)
if not isinstance(reposted_txo, Output) or not reposted_txo.can_decode_claim:
raise InputValueError(
f"A claim with id '{reposted_txo.claim_id}' was found but could not be decoded."
)
assert isinstance(reposted_txo.claim, Claim)
claim.repost.update(claim_type=reposted_txo.claim.claim_type, **kwargs)

if clear_channel:
claim.clear_signature()
Expand Down
4 changes: 2 additions & 2 deletions lbry/schema/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
build:
rm types/v2/* -rf
rm -rf types/v2/*
touch types/v2/__init__.py
cd types/v2/ && protoc --python_out=. -I ../../../../../types/v2/proto/ ../../../../../types/v2/proto/*.proto
cd types/v2/ && cp ../../../../../types/jsonschema/* ./
sed -e 's/^import\ \(.*\)_pb2\ /from . import\ \1_pb2\ /g' -i types/v2/*.py
sed -e 's/^import\ \(.*\)_pb2\ /from . import\ \1_pb2\ /g' -i.bak types/v2/*.py
99 changes: 99 additions & 0 deletions lbry/schema/attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@
from lbry.constants import COIN
from lbry.error import MissingPublishedFileError, EmptyPublishedFileError

import lbry.schema.claim as claim
from lbry.schema.mime_types import guess_media_type
from lbry.schema.base import Metadata, BaseMessageList
from lbry.schema.tags import clean_tags, normalize_tag
from lbry.schema.types.v2.claim_pb2 import (
Claim as ClaimMessage,
Fee as FeeMessage,
Location as LocationMessage,
Language as LanguageMessage
Expand Down Expand Up @@ -353,6 +355,96 @@ class ClaimReference(Metadata):

__slots__ = ()

def _set_claim_type(self, claim_type: str = None):
"""select the appropriate member (stream, channel, repost, or collection)"""
def _set_message(m):
old_type = claim.Claim(m).claim_type
if old_type and claim_type is None:
m.ClearField(old_type)
return
member = getattr(m, claim_type)
member.SetInParent()
_set_message(self.message.deletions)
_set_message(self.message.edits)

def update(self, claim_type: str, **kwargs) -> dict:
self._set_claim_type(claim_type)
print(f'update: {kwargs.items()}')
clear1 = dict(filter(lambda i: i[0].startswith('clear_'), kwargs.items()))
clear2 = dict(map(lambda i: (i[0][len('clear_'):], i[1]), clear1.items()))
self.deletions.update(**clear2)
edits1 = dict(filter(lambda i: not i[0].startswith('clear_'), kwargs.items()))
return self.edits.update(**edits1)

def apply(self, reposted: 'claim.Claim'):
# This mapping converts the full field names produced by
# flatten(claim.to_dict()) to the short names utilized by
# claim.update().
# TODO: Complete this...
short_name = {
'source_size': 'file_size',
'source_sd_hash': 'sd_hash',
'source_bt_infohash': 'bt_infohash',
'source_file_name': 'file_name',
'source_file_hash': 'file_hash',
'image_width': 'width',
'video_width': 'width',
'image_height': 'height',
'video_height': 'height',
'video_duration': 'duration',
'video_audio_duration': 'duration',
'audio_duration': 'duration',
}
def flatten(field, d, out):
if isinstance(d, dict):
for k, v in d.items():
subfield = f'{field}_{k}' if field else k
flatten(subfield, v, out)
else:
# d is a leaf value
try:
out[short_name.get(field, field)] = int(d)
except (ValueError, TypeError):
out[short_name.get(field, field)] = d
m = ClaimMessage()
m.CopyFrom(reposted.message)
result = claim.Claim(m)
if self.has_deletions and self.deletions.claim_type == reposted.claim_type:
clear1 = dict([(f'clear_{k}', v) for k, v in self.deletions.to_dict().items()])
print(f'{reposted.claim_type} deletions: {clear1}')
clear2 = dict()
flatten('', clear1, clear2)
print(f'{reposted.claim_type} deletions: {clear2}')
attr = getattr(result, result.claim_type)
attr.update(**clear2)
if self.has_edits and self.edits.claim_type == reposted.claim_type:
edits1 = self.edits.to_dict()
print(f'{reposted.claim_type} edits: {edits1}')
edits2 = dict()
flatten('', edits1, edits2)
print(f'{reposted.claim_type} edits: {edits2}')
attr = getattr(result, result.claim_type)
attr.update(**edits2)
return result

@property
def has_deletions(self) -> bool:
return self.message.HasField('deletions')

@property
def deletions(self) -> 'claim.BaseClaim':
c = claim.Claim(self.message.deletions)
return getattr(c, c.claim_type)

@property
def has_edits(self) -> bool:
return self.message.HasField('edits')

@property
def edits(self) -> 'claim.BaseClaim':
c = claim.Claim(self.message.edits)
return getattr(c, c.claim_type)

@property
def claim_id(self) -> str:
return hexlify(self.claim_hash[::-1]).decode()
Expand Down Expand Up @@ -449,6 +541,13 @@ class LanguageList(BaseMessageList[Language]):
def append(self, value: str):
self.add().langtag = value

def remove(self, value: str) -> bool:
r = 0
for i, v in enumerate(self):
if v.langtag == value:
del self[i]
r += 1
return r > 0

class Location(Metadata):

Expand Down
46 changes: 40 additions & 6 deletions lbry/schema/claim.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def none_check(self, kwargs):
if value is None:
raise InputValueIsNoneError(key)

def update(self, **kwargs):
def update(self, strict_update=True, **kwargs) -> dict:
self.none_check(kwargs)

for key in list(kwargs):
Expand All @@ -136,8 +136,22 @@ def update(self, **kwargs):

for l in self.repeat_fields:
field = getattr(self, l)
if kwargs.pop(f'clear_{l}', False):
del field[:]
clear = kwargs.pop(f'clear_{l}', False)
if isinstance(clear, bool) and clear:
failed = []
if len(field) > 0:
del field[:]
else:
failed = clear
if failed:
kwargs[f'clear_{l}'] = failed
if isinstance(clear, list):
failed = []
for c in clear:
if not field.remove(c):
failed.append(c)
if failed:
kwargs[f'clear_{l}'] = failed
items = kwargs.pop(l, None)
if items is not None:
if isinstance(items, str):
Expand All @@ -147,8 +161,16 @@ def update(self, **kwargs):
else:
raise ValueError(f"Unknown {l} value: {items}")

failed = dict()
for key, value in kwargs.items():
setattr(self, key, value)
try:
setattr(self, key, value)
except AttributeError:
failed[key] = value
if strict_update:
raise

return failed

@property
def title(self) -> str:
Expand Down Expand Up @@ -213,7 +235,7 @@ def to_dict(self):
fee['amount'] = str(self.fee.amount)
return claim

def update(self, file_path=None, height=None, width=None, duration=None, **kwargs):
def update(self, file_path=None, height=None, width=None, duration=None, **kwargs) -> dict:

if kwargs.pop('clear_fee', False):
self.message.ClearField('fee')
Expand Down Expand Up @@ -264,7 +286,7 @@ def update(self, file_path=None, height=None, width=None, duration=None, **kwarg
media_args['width'] = width
media.update(**media_args)

super().update(**kwargs)
return super().update(**kwargs)

@property
def author(self) -> str:
Expand Down Expand Up @@ -398,6 +420,18 @@ class Repost(BaseClaim):

claim_type = Claim.REPOST

def update(self, **kwargs) -> dict:
claim_type = kwargs.pop('claim_type', None)
# Update common fields within BaseClaim.
kwargs = super().update(strict_update=False, **kwargs)
if claim_type:
# Remaining updates go into deletes/edits of ClaimReference.
kwargs = self.reference.update(claim_type, **kwargs)
return kwargs
Comment on lines +423 to +430
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See PR description. This is where I have a choice of applying the update to BaseClaim or stuff it inside ClaimReference.


def apply(self, reposted: 'Claim'):
return self.reference.apply(reposted)

@property
def reference(self) -> ClaimReference:
return ClaimReference(self.message)
Expand Down
2 changes: 1 addition & 1 deletion lbry/schema/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def message_to_txo(self, txo_message, tx_map):
if claim.HasField('channel'):
txo.channel = tx_map[claim.channel.tx_hash].outputs[claim.channel.nout]
if claim.HasField('repost'):
txo.reposted_claim = tx_map[claim.repost.tx_hash].outputs[claim.repost.nout]
txo.original_reposted_claim = tx_map[claim.repost.tx_hash].outputs[claim.repost.nout]
try:
if txo.claim.is_channel:
txo.meta['claims_in_channel'] = claim.claims_in_channel
Expand Down
4,729 changes: 49 additions & 4,680 deletions lbry/schema/types/v2/claim_pb2.py

Large diffs are not rendered by default.

66 changes: 11 additions & 55 deletions lbry/schema/types/v2/purchase_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading