Convert Metadata and Fee validators to use new JSON Schema-based system
This commit is contained in:
parent
3f22f39ce1
commit
d8d462f43c
4 changed files with 329 additions and 169 deletions
|
@ -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)
|
||||
|
||||
|
||||
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),
|
||||
self._versions = [
|
||||
('0.0.1', fee_schemas.VER_001, None)
|
||||
]
|
||||
|
||||
FEE_MIGRATIONS = []
|
||||
StructuredDict.__init__(self, fee, fee.get('ver', '0.0.1'))
|
||||
|
||||
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)
|
||||
log.error('Failed to convert fee amount %s to float', amt)
|
||||
raise
|
||||
|
||||
|
||||
class LBCFeeValidator(StructuredDict):
|
||||
pass
|
||||
|
||||
|
||||
class BTCFeeValidator(StructuredDict):
|
||||
pass
|
||||
|
||||
|
||||
class USDFeeValidator(StructuredDict):
|
||||
pass
|
||||
|
|
|
@ -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(Validator):
|
||||
MV001 = "0.0.1"
|
||||
MV002 = "0.0.2"
|
||||
MV003 = "0.0.3"
|
||||
CURRENT_METADATA_VERSION = MV003
|
||||
|
||||
METADATA_REVISIONS = {}
|
||||
|
||||
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),
|
||||
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)
|
||||
]
|
||||
|
||||
METADATA_REVISIONS[MV002] = [
|
||||
(Validator.REQUIRE, 'nsfw', skip_validate),
|
||||
(Validator.REQUIRE, 'ver', skip_validate),
|
||||
(Validator.OPTIONAL, 'license_url', skip_validate),
|
||||
]
|
||||
starting_version = metadata.get('ver', '0.0.1')
|
||||
|
||||
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),
|
||||
]
|
||||
StructuredDict.__init__(self, metadata, starting_version, migrate, target_version)
|
||||
|
||||
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),
|
||||
]
|
||||
def _migrate_001_to_002(self):
|
||||
self['ver'] = '0.0.2'
|
||||
|
||||
METADATA_MIGRATIONS = [
|
||||
MIGRATE_MV001_TO_MV002,
|
||||
MIGRATE_MV002_TO_MV003,
|
||||
]
|
||||
def _migrate_002_to_003(self):
|
||||
self['ver'] = '0.0.3'
|
||||
|
||||
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']
|
16
lbrynet/metadata/fee_schemas.py
Normal file
16
lbrynet/metadata/fee_schemas.py
Normal file
|
@ -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'
|
||||
}
|
||||
},
|
||||
}
|
269
lbrynet/metadata/metadata_schemas.py
Normal file
269
lbrynet/metadata/metadata_schemas.py
Normal file
|
@ -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']
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue