diff --git a/lbrynet/metadata/Fee.py b/lbrynet/metadata/Fee.py index 870d5f3b1..0e77b3cfe 100644 --- a/lbrynet/metadata/Fee.py +++ b/lbrynet/metadata/Fee.py @@ -1,116 +1,39 @@ import logging +import fee_schemas -from lbrynet.metadata.Validator import Validator, skip_validate -from lbrynet.conf import CURRENCIES +from lbrynet.metadata.StructuredDict import StructuredDict log = logging.getLogger(__name__) -def verify_supported_currency(fee): - assert len(fee) == 1 - for c in fee: - assert c in CURRENCIES - return True - - -def verify_amount(x): - return isinstance(x, float) or isinstance(x, int) and x > 0 - - -class LBCFeeValidator(Validator): - FV001 = "0.0.1" - CURRENT_FEE_VERSION = FV001 - - FEE_REVISIONS = {} - - FEE_REVISIONS[FV001] = [ - (Validator.REQUIRE, 'amount', verify_amount), - (Validator.REQUIRE, 'address', skip_validate), - ] - - FEE_MIGRATIONS = [] - - current_version = CURRENT_FEE_VERSION - versions = FEE_REVISIONS - migrations = FEE_MIGRATIONS - +class FeeValidator(StructuredDict): def __init__(self, fee): - Validator.__init__(self, fee) + self._versions = [ + ('0.0.1', fee_schemas.VER_001, None) + ] + StructuredDict.__init__(self, fee, fee.get('ver', '0.0.1')) -class BTCFeeValidator(Validator): - FV001 = "0.0.1" - CURRENT_FEE_VERSION = FV001 - - FEE_REVISIONS = {} - - FEE_REVISIONS[FV001] = [ - (Validator.REQUIRE, 'amount',verify_amount), - (Validator.REQUIRE, 'address', skip_validate), - ] - - FEE_MIGRATIONS = [] - - current_version = CURRENT_FEE_VERSION - versions = FEE_REVISIONS - migrations = FEE_MIGRATIONS - - def __init__(self, fee): - Validator.__init__(self, fee) - - -class USDFeeValidator(Validator): - FV001 = "0.0.1" - CURRENT_FEE_VERSION = FV001 - - FEE_REVISIONS = {} - - FEE_REVISIONS[FV001] = [ - (Validator.REQUIRE, 'amount',verify_amount), - (Validator.REQUIRE, 'address', skip_validate), - ] - - FEE_MIGRATIONS = [] - - current_version = CURRENT_FEE_VERSION - versions = FEE_REVISIONS - migrations = FEE_MIGRATIONS - - def __init__(self, fee): - Validator.__init__(self, fee) - - -class FeeValidator(Validator): - CV001 = "0.0.1" - CURRENT_CURRENCY_VERSION = CV001 - - CURRENCY_REVISIONS = {} - - CURRENCY_REVISIONS[CV001] = [ - (Validator.OPTIONAL, 'BTC', BTCFeeValidator.validate), - (Validator.OPTIONAL, 'USD', USDFeeValidator.validate), - (Validator.OPTIONAL, 'LBC', LBCFeeValidator.validate), - ] - - CURRENCY_MIGRATIONS = [] - - current_version = CURRENT_CURRENCY_VERSION - versions = CURRENCY_REVISIONS - migrations = CURRENCY_MIGRATIONS - - def __init__(self, fee_dict): - Validator.__init__(self, fee_dict) self.currency_symbol = self.keys()[0] self.amount = self._get_amount() self.address = self[self.currency_symbol]['address'] def _get_amount(self): amt = self[self.currency_symbol]['amount'] - if isinstance(amt, float): - return amt - else: - try: - return float(amt) - except TypeError: - log.error('Failed to convert %s to float', amt) - raise + try: + return float(amt) + except TypeError: + log.error('Failed to convert fee amount %s to float', amt) + raise + + +class LBCFeeValidator(StructuredDict): + pass + + +class BTCFeeValidator(StructuredDict): + pass + + +class USDFeeValidator(StructuredDict): + pass diff --git a/lbrynet/metadata/Metadata.py b/lbrynet/metadata/Metadata.py index f1294a95e..3349ed2f9 100644 --- a/lbrynet/metadata/Metadata.py +++ b/lbrynet/metadata/Metadata.py @@ -1,8 +1,8 @@ import logging -from lbrynet.metadata.Validator import Validator, skip_validate -from lbrynet.metadata.Fee import FeeValidator, verify_supported_currency +from lbrynet.metadata.StructuredDict import StructuredDict from lbrynet.conf import SOURCE_TYPES +import metadata_schemas log = logging.getLogger(__name__) NAME_ALLOWED_CHARSET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0987654321-' @@ -14,73 +14,25 @@ def verify_name_characters(name): return True -def validate_sources(sources): - for source in sources: - assert source in SOURCE_TYPES, "Unknown source type: %s" % str(source) - return True +class Metadata(StructuredDict): + def __init__(self, metadata, migrate=True, target_version=None): + self._versions = [ + ('0.0.1', metadata_schemas.VER_001, None), + ('0.0.2', metadata_schemas.VER_002, self._migrate_001_to_002), + ('0.0.3', metadata_schemas.VER_003, self._migrate_002_to_003) + ] + + starting_version = metadata.get('ver', '0.0.1') + + StructuredDict.__init__(self, metadata, starting_version, migrate, target_version) -class Metadata(Validator): - MV001 = "0.0.1" - MV002 = "0.0.2" - MV003 = "0.0.3" - CURRENT_METADATA_VERSION = MV003 + def _migrate_001_to_002(self): + self['ver'] = '0.0.2' - METADATA_REVISIONS = {} + def _migrate_002_to_003(self): + self['ver'] = '0.0.3' - METADATA_REVISIONS[MV001] = [ - (Validator.REQUIRE, 'title', skip_validate), - (Validator.REQUIRE, 'description', skip_validate), - (Validator.REQUIRE, 'author', skip_validate), - (Validator.REQUIRE, 'language', skip_validate), - (Validator.REQUIRE, 'license', skip_validate), - (Validator.REQUIRE, 'content-type', skip_validate), - (Validator.REQUIRE, 'sources', validate_sources), - (Validator.OPTIONAL, 'thumbnail', skip_validate), - (Validator.OPTIONAL, 'preview', skip_validate), - (Validator.OPTIONAL, 'fee', verify_supported_currency), - (Validator.OPTIONAL, 'contact', skip_validate), - (Validator.OPTIONAL, 'pubkey', skip_validate), - ] - - METADATA_REVISIONS[MV002] = [ - (Validator.REQUIRE, 'nsfw', skip_validate), - (Validator.REQUIRE, 'ver', skip_validate), - (Validator.OPTIONAL, 'license_url', skip_validate), - ] - - METADATA_REVISIONS[MV003] = [ - (Validator.REQUIRE, 'content_type', skip_validate), - (Validator.SKIP, 'content-type'), - (Validator.OPTIONAL, 'sig', skip_validate), - (Validator.IF_KEY, 'sig', (Validator.REQUIRE, 'pubkey', skip_validate), Validator.DO_NOTHING), - (Validator.IF_KEY, 'pubkey', (Validator.REQUIRE, 'sig', skip_validate), Validator.DO_NOTHING), - ] - - MIGRATE_MV001_TO_MV002 = [ - (Validator.IF_KEY, 'nsfw', Validator.DO_NOTHING, (Validator.LOAD, 'nsfw', False)), - (Validator.IF_KEY, 'ver', Validator.DO_NOTHING, (Validator.LOAD, 'ver', MV002)), - ] - - MIGRATE_MV002_TO_MV003 = [ - (Validator.IF_KEY, 'content-type', (Validator.UPDATE, 'content-type', 'content_type'), Validator.DO_NOTHING), - (Validator.IF_VAL, 'ver', MV002, (Validator.LOAD, 'ver', MV003), Validator.DO_NOTHING), - ] - - METADATA_MIGRATIONS = [ - MIGRATE_MV001_TO_MV002, - MIGRATE_MV002_TO_MV003, - ] - - current_version = CURRENT_METADATA_VERSION - versions = METADATA_REVISIONS - migrations = METADATA_MIGRATIONS - - def __init__(self, metadata, process_now=True): - Validator.__init__(self, metadata, process_now) - self.meta_version = self.get('ver', Metadata.MV001) - self._load_fee() - - def _load_fee(self): - if 'fee' in self: - self.update({'fee': FeeValidator(self['fee'])}) + if 'content-type' in self: + self['content_type'] = self['content-type'] + del self['content-type'] \ No newline at end of file diff --git a/lbrynet/metadata/fee_schemas.py b/lbrynet/metadata/fee_schemas.py new file mode 100644 index 000000000..18efd64b6 --- /dev/null +++ b/lbrynet/metadata/fee_schemas.py @@ -0,0 +1,16 @@ +VER_001 = { + '$schema': 'http://json-schema.org/draft-04/schema#', + 'title': 'LBRY fee schema 0.0.1', + 'type': 'object', + + 'properties': { + 'amount': { + 'type': 'number', + 'minimum': 0, + 'exclusiveMinimum': True, + }, + 'address': { + 'type': 'string' + } + }, +} diff --git a/lbrynet/metadata/metadata_schemas.py b/lbrynet/metadata/metadata_schemas.py new file mode 100644 index 000000000..2f66a3c74 --- /dev/null +++ b/lbrynet/metadata/metadata_schemas.py @@ -0,0 +1,269 @@ +VER_001 = { + '$schema': 'http://json-schema.org/draft-04/schema#', + 'title': 'LBRY metadata schema 0.0.1', + 'definitions': { + 'fee_info': { + 'type': 'object', + 'properties': { + 'amount': { + 'type': 'number', + 'minimum': 0, + 'exclusiveMinimum': True, + }, + 'address': { + 'type': 'string' + } + }, + } + }, + 'type': 'object', + + 'properties': { + 'ver': { + 'type': 'string', + 'default': '0.0.1' + }, + 'title': { + 'type': 'string' + }, + 'description': { + 'type': 'string' + }, + 'author': { + 'type': 'string' + }, + 'language': { + 'type': 'string' + }, + 'license': { + 'type': 'string' + }, + 'content-type': { + 'type': 'string' + }, + 'sources': { + 'type': 'object', + 'properties': { + 'lbry_sd_hash': { + 'type': 'string' + }, + 'btih': { + 'type': 'string' + }, + 'url': { + 'type': 'string' + } + }, + 'additionalProperties': False + }, + 'thumbnail': { + 'type': 'string' + }, + 'preview': { + 'type': 'string' + }, + 'fee': { + 'properties': { + 'LBC': { '$ref': '#/definitions/fee_info' }, + 'BTC': { '$ref': '#/definitions/fee_info' }, + 'USD': { '$ref': '#/definitions/fee_info' } + } + }, + 'contact': { + 'type': 'number' + }, + 'pubkey': { + 'type': 'string' + }, + }, + 'required': ['title', 'description', 'author', 'language', 'license', 'content-type', 'sources'], + 'additionalProperties': False +} + + +VER_002 = { + '$schema': 'http://json-schema.org/draft-04/schema#', + 'title': 'LBRY metadata schema 0.0.2', + 'definitions': { + 'fee_info': { + 'type': 'object', + 'properties': { + 'amount': { + 'type': 'number', + 'minimum': 0, + 'exclusiveMinimum': True, + }, + 'address': { + 'type': 'string' + } + }, + } + }, + 'type': 'object', + + 'properties': { + 'ver': { + 'type': 'string', + 'enum': ['0.0.2'], + }, + 'title': { + 'type': 'string' + }, + 'description': { + 'type': 'string' + }, + 'author': { + 'type': 'string' + }, + 'language': { + 'type': 'string' + }, + 'license': { + 'type': 'string' + }, + 'content-type': { + 'type': 'string' + }, + 'sources': { + 'type': 'object', + 'properties': { + 'lbry_sd_hash': { + 'type': 'string' + }, + 'btih': { + 'type': 'string' + }, + 'url': { + 'type': 'string' + } + }, + 'additionalProperties': False + }, + 'thumbnail': { + 'type': 'string' + }, + 'preview': { + 'type': 'string' + }, + 'fee': { + 'properties': { + 'LBC': { '$ref': '#/definitions/fee_info' }, + 'BTC': { '$ref': '#/definitions/fee_info' }, + 'USD': { '$ref': '#/definitions/fee_info' } + } + }, + 'contact': { + 'type': 'number' + }, + 'pubkey': { + 'type': 'string' + }, + 'license_url': { + 'type': 'string' + }, + 'nsfw': { + 'type': 'boolean', + 'default': False + }, + + }, + 'required': ['ver', 'title', 'description', 'author', 'language', 'license', 'content-type', 'sources', 'nsfw'], + 'additionalProperties': False +} + + +VER_003 = { + '$schema': 'http://json-schema.org/draft-04/schema#', + 'title': 'LBRY metadata schema 0.0.3', + 'definitions': { + 'fee_info': { + 'type': 'object', + 'properties': { + 'amount': { + 'type': 'number', + 'minimum': 0, + 'exclusiveMinimum': True, + }, + 'address': { + 'type': 'string' + } + }, + } + }, + 'type': 'object', + + 'properties': { + 'ver': { + 'type': 'string', + 'enum': ['0.0.3'], + }, + 'title': { + 'type': 'string' + }, + 'description': { + 'type': 'string' + }, + 'author': { + 'type': 'string' + }, + 'language': { + 'type': 'string' + }, + 'license': { + 'type': 'string' + }, + 'content_type': { + 'type': 'string' + }, + 'sources': { + 'type': 'object', + 'properties': { + 'lbry_sd_hash': { + 'type': 'string' + }, + 'btih': { + 'type': 'string' + }, + 'url': { + 'type': 'string' + } + }, + 'additionalProperties': False + }, + 'thumbnail': { + 'type': 'string' + }, + 'preview': { + 'type': 'string' + }, + 'fee': { + 'properties': { + 'LBC': { '$ref': '#/definitions/fee_info' }, + 'BTC': { '$ref': '#/definitions/fee_info' }, + 'USD': { '$ref': '#/definitions/fee_info' } + } + }, + 'contact': { + 'type': 'number' + }, + 'pubkey': { + 'type': 'string' + }, + 'license_url': { + 'type': 'string' + }, + 'nsfw': { + 'type': 'boolean', + 'default': False + }, + 'sig': { + 'type': 'string' + } + }, + 'required': ['ver', 'title', 'description', 'author', 'language', 'license', 'content_type', 'sources', 'nsfw'], + 'additionalProperties': False, + 'dependencies': { + 'pubkey': ['sig'], + 'sig': ['pubkey'] + } +}