def test_pick_tree(self): src = { 'a': 'a', 'b': { 'x': 'b.x', 'y': 'b.y' }, 'b.x': 'b-dot-x', 'c': [ { 'x': 'c0.x', 'y': 'c0.y' }, { 'x': 'c1.x', 'y': 'c1.y' }, ], } self.assertEqual(morph.pick(src, 'a', 'b.x', tree=True), { 'a': 'a', 'b': { 'x': 'b.x' } }) self.assertEqual(morph.pick(src, 'a', 'b.x'), { 'a': 'a', 'b.x': 'b-dot-x' })
def _getOptions(context): if __name__ in context: return context[__name__] options = aadict.d2ar(morph.pick(context.options, prefix='access.')) # `options.groups` = all known groups LUT options.groups = { k : aadict({'docorator': v, 'class': list(_docorator2classes(v))[0]}) for k, v in morph.pick(options, prefix='group.').items() } # `options.default` = default access for endpoint, type, and attribute options.default = aadict({ node : morph.tolist(options.get('default.' + node)) for node in ('endpoint', 'type', 'attribute') }) # `options.rank.groups` = ordered list of group ranking (most-public to least-public) options.rank = aadict(groups=morph.tolist(options.rank)) # `options.rank.classes` = ordered list of class ranking options.rank.classes = [options.groups[grp]['class'] for grp in options.rank.groups] # `options.rank.docorators` = ordered list of docorator ranking options.rank.docorators = [options.groups[grp]['docorator'] for grp in options.rank.groups] # `options.default[NODE].(groups|classes|docorators)` for node, groups in list(options.default.items()): options.default[node] = aadict( groups = groups, classes = [options.groups[grp]['class'] for grp in groups], docorators = [options.groups[grp]['docorator'] for grp in groups], ) # `options.classes` = all known access classes options.classes = [ group['class'] for group in options.groups.values()] # `options.docorators` = all known access docorators options.docorators = [ group['docorator'] for group in options.groups.values()] # `options.request` = current request information options.request = aadict() # `options.control` = request-to-group-access callback if not options.control: options.control = _defaultAccessControl if options.control == GLOBAL_ACCESS: options.request.groups = options.groups.keys() else: options.control = asset.symbol(options.control) options.request.groups = options.control(context.request, context=context) # `options.request.classes` = the classes this request has access to options.request.classes = [ options.groups[group]['class'] for group in options.request.groups if group in options.groups ] # `options.request.docorators` = the docorators this request has access to options.request.docorators = [ options.groups[group]['docorator'] for group in options.request.groups if group in options.groups ] context[__name__] = options return options
def assertSeqEqual(self, result, expected, pick=None): ''' Helper method to compare two sequences. If `pick` is specified, then it would only compares those attributes for each object. ''' if pick is not None and morph.isseq(result) and morph.isseq(expected): result = [morph.pick(item, *morph.tolist(pick)) for item in result] expected = [morph.pick(item, *morph.tolist(pick)) for item in expected] # print '=== result ===' # print result # print '=== expected ===' # print expected self.assertEqual(result, expected, 'the sequences are different')
def reg2api(record, name): record = aadict(record) # reg: {'rid':'55026','zid':'4442','domainid':'12345','type':'A', # 'name':'fh3.example.ly','ttl':'14400','content':'10.11.12.237',} ret = api.Record(name=absdom(record.name), rclass='IN', ttl=int(record.ttl), **morph.pick(record, 'rid', 'zid', 'domainid', 'type', 'content')) if ret.type not in api.Record.TYPES: raise api.DriverError( _('unknown/unexpected Registerly record type: "{}"', ret.type)) if ret.type in (api.Record.TYPE_MX, api.Record.TYPE_CNAME, api.Record.TYPE_NS): ret.update(content=absdom(ret.content)) if ret.type == api.Record.TYPE_SOA: # there's stuff missing!... content form should be: # {root} {contact} {serial} {refresh} {retry} {expire} {minttl} # but is comming back as: # ns1.libyanspider.com support.libyanspider.com 0 # so fetching from DNS... ugh. return ret.update(content=regGetSoaContent(name)) if ret.type == api.Record.TYPE_MX: return ret.update(priority=int(record.prio)) if ret.type == api.Record.TYPE_CNAME: return ret.update(content=absdom(ret.content)) # TODO: verify api.Record.TYPE_SRV... # TODO: verify api.Record.TYPE_NAPTR... # todo: Registerly also supports "PTR" and "URL" records... hm... return ret
def factory(handler, registry): get = morph.pick(registry.settings, prefix=CONFIG_PREFIX).get conf = aadict() conf.enabled = asbool(get('enabled', True)) conf.include = [globre.compile(el, globre.EXACT) for el in aslist(get('include', []))] conf.exclude = [globre.compile(el, globre.EXACT) for el in aslist(get('exclude', []))] conf.reparse = aslist(get('reparse-methods', DEFAULT_REPARSE_METHODS)) conf.name = get('attribute-name', DEFAULT_ATTRIBUTE_NAME) conf.deep = asbool(get('combine.deep', True)) conf.reqdict = asbool(get('require-dict', True)) conf.failunk = asbool(get('fail-unknown', True)) conf.ndict = asbool(get('native-dict', False)) conf.error = get('error-handler', None) if conf.error: conf.error = asset.symbol(conf.error) conf.xfmt = asbool(get('xml.enable', True)) conf.jfmt = asbool(get('json.enable', True)) conf.yfmt = asbool(get('yaml.enable', bool(yaml or get('yaml.parser')))) if conf.jfmt: conf.jparser = get('json.parser', None) if conf.jparser: conf.jparser = asset.symbol(conf.jparser) if conf.yfmt: conf.yparser = asset.symbol(get('yaml.parser', 'yaml.load')) if conf.xfmt: conf.xparser = asset.symbol(get('xml.parser', 'xml.etree.ElementTree.fromstring')) def input_tween(request): return process(handler, request, conf) return input_tween
def reg2api(record, name): record = aadict(record) # reg: {'rid':'55026','zid':'4442','domainid':'12345','type':'A', # 'name':'fh3.example.ly','ttl':'14400','content':'10.11.12.237',} ret = api.Record( name = absdom(record.name), rclass = 'IN', ttl = int(record.ttl), **morph.pick(record, 'rid', 'zid', 'domainid', 'type', 'content')) if ret.type not in api.Record.TYPES: raise api.DriverError( _('unknown/unexpected Registerly record type: "{}"', ret.type)) if ret.type in (api.Record.TYPE_MX, api.Record.TYPE_CNAME, api.Record.TYPE_NS): ret.update(content = absdom(ret.content)) if ret.type == api.Record.TYPE_SOA: # there's stuff missing!... content form should be: # {root} {contact} {serial} {refresh} {retry} {expire} {minttl} # but is comming back as: # ns1.libyanspider.com support.libyanspider.com 0 # so fetching from DNS... ugh. return ret.update(content = regGetSoaContent(name)) if ret.type == api.Record.TYPE_MX: return ret.update(priority = int(record.prio)) if ret.type == api.Record.TYPE_CNAME: return ret.update(content = absdom(ret.content)) # TODO: verify api.Record.TYPE_SRV... # TODO: verify api.Record.TYPE_NAPTR... # todo: Registerly also supports "PTR" and "URL" records... hm... return ret
def assertApiOk(self, response, expected=None, contentType='application/json', location=None, root=None, sideload=None, pick=None, pluck=None, omit=None, sort=None): if location is not None: self.assertEqual(response.status_code, 302) if morph.isstr(location): self.assertEqual(response.headers['location'], location) else: self.assertTrue(location(response.headers['location'])) return response self.assertEqual(response.status_code, 200) self.assertEqual(response.content_type, contentType) if expected is None: return response if contentType == 'text/html': self.assertEqual(response.body, expected) return response result = response.json_body if root is not None: self.assertIn(root, result, 'root "%s" not found in response' % (root,)) self.assertEqual(result.keys(), [root] if not sideload else [root] + sideload) result = result[root] if pick is not None: if morph.isdict(expected): result = morph.pick(result, *morph.tolist(pick)) elif morph.isseq(expected): result = [morph.pick(item, *morph.tolist(pick)) for item in result] if pluck is not None: result = [item.get(pluck, None) for item in result] if omit is not None: if morph.isdict(expected): result = morph.omit(result, *morph.tolist(omit)) expected = morph.omit(expected, *morph.tolist(omit)) elif morph.isseq(expected): result = [morph.omit(item, *morph.tolist(omit)) for item in result] expected = [morph.omit(item, *morph.tolist(omit)) for item in expected] if sort: if sort is True: expected = sorted(expected) result = sorted(result) else: expected = sort(expected) result = sort(result) self.assertEqual(result, expected) return response
def assertSeqEqual(self, result, expected, pick=None): ''' Helper method to compare two sequences. If `pick` is specified, then it would only compares those attributes for each object. ''' if pick is not None and morph.isseq(result) and morph.isseq(expected): result = [morph.pick(item, *morph.tolist(pick)) for item in result] expected = [ morph.pick(item, *morph.tolist(pick)) for item in expected ] # print '=== result ===' # print result # print '=== expected ===' # print expected self.assertEqual(result, expected, 'the sequences are different')
def n2j(self, note): data = morph.pick(note, *api.Note.ATTRIBUTES) content = data.get('content','') if note.secure: data['digest'] = 'sha256:' + hashlib.sha256(content).hexdigest() data['content'] = self.encrypt(content, symmetric=False) data['signature'] = signData(data['content'], self.getPrivateKey()) return data
def __init__(self, settings=None, default=None, override=None): self.settings = adict(settings or dict()) self.include = [reparse(expr) if isstr(expr) else expr for expr in tolist(self.settings.include or '')] self.exclude = [reparse(expr) if isstr(expr) else expr for expr in tolist(self.settings.exclude or '')] self.formats = tolist(self.settings.formats or '') or FORMATS self.defformat = self.settings.get('format.default', self.formats[0]) # load the renderer, default and override options self.renderers = dict() self.options = dict() self.override = dict() self.options[None] = extract(self.settings, 'format.default') self.options[None].update(default or dict()) self.override[None] = extract(self.settings, 'format.override') self.override[None].update(override or dict()) # note that all format settings must be extracted since there may # be cascaded formatting calls (instead of just restricting it to # the set in `self.formats`... fmts = set([k.split('.', 2)[1] for k in self.settings.keys() if k.startswith('format.') and '.' in k[8:]]) fmts -= set(['default', 'override']) for fmt in fmts: rndr = self.settings.get('format.' + fmt + '.renderer', None) if rndr: self.renderers[fmt] = rndr self.options[fmt] = extract(self.settings, 'format.' + fmt + '.default') self.override[fmt] = extract(self.settings, 'format.' + fmt + '.override') # load the entry/type/catalog parsers and filters stropts = dict(self.str_options) self.eparsers = asset.plugins( 'pyramid_describe.plugins.entry.parsers', self.settings.get('entry.parsers', stropts.get('entry.parsers'))) self.tparsers = asset.plugins( 'pyramid_describe.plugins.type.parsers', self.settings.get('type.parsers', stropts.get('type.parsers'))) self.cparsers = asset.plugins( 'pyramid_describe.plugins.catalog.parsers', self.settings.get('catalog.parsers', stropts.get('catalog.parsers'))) self.efilters = asset.plugins( 'pyramid_describe.plugins.entry.filters', self.settings.get('entry.filters', stropts.get('entry.filters'))) self.tfilters = asset.plugins( 'pyramid_describe.plugins.type.filters', self.settings.get('type.filters', stropts.get('type.filters'))) self.cfilters = asset.plugins( 'pyramid_describe.plugins.catalog.filters', self.settings.get('catalog.filters', stropts.get('catalog.filters'))) self.render_template = self.settings.get('render.template', None) self.methOrderKey = methOrderKey( tolist(self.settings.get('methods.order', DEFAULT_METHODS_ORDER))) tropts = morph.pick(self.settings, prefix='typereg.') tropts['commentToken'] = self.settings.get( 'commentToken', dict(self.str_options).get('commentToken')) self.typereg = TypeRegistry(tropts)
def test_pick(self): class aadict(dict): pass d = aadict(foo='bar', zig=87, ziggy=78) self.assertEqual(morph.pick(d, 'foo'), {'foo': 'bar'}) self.assertEqual(morph.pick(d, 'foo', dict=aadict), {'foo': 'bar'}) self.assertEqual(morph.pick(d), {}) self.assertEqual(morph.pick(d, prefix='zi'), {'g': 87, 'ggy': 78}) self.assertIsInstance(morph.pick(d, 'foo'), dict) self.assertNotIsInstance(morph.pick(d, 'foo'), aadict) self.assertIsInstance(morph.pick(d, 'foo', dict=aadict), aadict) self.assertEqual(morph.pick(d), {})
def test_pick_object(self): class Thing(object): def __init__(self): self.foo = 'bar' self.zig1 = 'zog' self.zig2 = 'zug' def zigSomeMethod(self): pass src = Thing() self.assertEqual(morph.pick(src, 'foo', 'zig1'), { 'zig1': 'zog', 'foo': 'bar' }) self.assertEqual(morph.pick(src, prefix='zig'), { '1': 'zog', '2': 'zug' }) self.assertEqual(morph.pick(src), {})
def _load_service_config(self, app, component): # fetch setvice definition with minimum structure svc = self._fetch_service_config(app) # always assume a .deis.io/ ending component = "%s.deis.io/" % component # Filter to only include values for the component and strip component out of it # Processes dots into a nested structure config = morph.unflatten(morph.pick(svc['metadata']['annotations'], prefix=component)) return config
def _load_service_config(self, app, component, svc_name=None): # fetch setvice definition with minimum structure svc = self._fetch_service_config(app, svc_name) # always assume a .drycc.cc/ ending component = "%s.drycc.cc/" % component # Filter to only include values for the component and strip component out of it # Processes dots into a nested structure config = morph.unflatten(morph.pick(svc['metadata']['annotations'], prefix=component)) return config
def __init__(self, options=None, aliases=None, _hack=False): if _hack: return self.options = aadict(self.DEFAULT_OPTIONS).update(options or {}) self._types = dict() self._autotypes = dict() self._aliases = dict() self._dictType_cre = re.compile(self.options.customDictTypeRE) self._unknownType_cre = re.compile(self.options.unknownTypeRE) aliases = aliases or self.options.aliases self.addAliases(self.DEFAULT_ALIASES if aliases is None else aliases) if aliases is None: self.addHttpAliases() for target, val in morph.pick(self.options, prefix='alias.').items(): for source in morph.tolist(val): self.addAlias(source, target) if self.options.extensions: self.loadExtensions(self.options.extensions)
def _getOptions(context): if __name__ in context: return context[__name__] options = aadict.d2ar(morph.pick(context.options, prefix='access.')) # `options.groups` = all known groups LUT options.groups = { k: aadict({ 'docorator': v, 'class': list(_docorator2classes(v))[0] }) for k, v in morph.pick(options, prefix='group.').items() } # `options.default` = default access for endpoint, type, and attribute options.default = aadict({ node: morph.tolist(options.get('default.' + node)) for node in ('endpoint', 'type', 'attribute') }) # `options.rank.groups` = ordered list of group ranking (most-public to least-public) options.rank = aadict(groups=morph.tolist(options.rank)) # `options.rank.classes` = ordered list of class ranking options.rank.classes = [ options.groups[grp]['class'] for grp in options.rank.groups ] # `options.rank.docorators` = ordered list of docorator ranking options.rank.docorators = [ options.groups[grp]['docorator'] for grp in options.rank.groups ] # `options.default[NODE].(groups|classes|docorators)` for node, groups in list(options.default.items()): options.default[node] = aadict( groups=groups, classes=[options.groups[grp]['class'] for grp in groups], docorators=[options.groups[grp]['docorator'] for grp in groups], ) # `options.classes` = all known access classes options.classes = [group['class'] for group in options.groups.values()] # `options.docorators` = all known access docorators options.docorators = [ group['docorator'] for group in options.groups.values() ] # `options.request` = current request information options.request = aadict() # `options.control` = request-to-group-access callback if not options.control: options.control = _defaultAccessControl if options.control == GLOBAL_ACCESS: options.request.groups = options.groups.keys() else: options.control = asset.symbol(options.control) options.request.groups = options.control(context.request, context=context) # `options.request.classes` = the classes this request has access to options.request.classes = [ options.groups[group]['class'] for group in options.request.groups if group in options.groups ] # `options.request.docorators` = the docorators this request has access to options.request.docorators = [ options.groups[group]['docorator'] for group in options.request.groups if group in options.groups ] context[__name__] = options return options
def update(self, *args, **kw): for k, v in morph.pick(dict(*args, **kw), *self.ATTRIBUTES).items(): setattr(self, k, v) return self
def __init__(self, settings=None, default=None, override=None): self.settings = adict(settings or dict()) self.include = [ reparse(expr) if isstr(expr) else expr for expr in tolist(self.settings.include or '') ] self.exclude = [ reparse(expr) if isstr(expr) else expr for expr in tolist(self.settings.exclude or '') ] self.formats = tolist(self.settings.formats or '') or FORMATS self.defformat = self.settings.get('format.default', self.formats[0]) # load the renderer, default and override options self.renderers = dict() self.options = dict() self.override = dict() self.options[None] = extract(self.settings, 'format.default') self.options[None].update(default or dict()) self.override[None] = extract(self.settings, 'format.override') self.override[None].update(override or dict()) # note that all format settings must be extracted since there may # be cascaded formatting calls (instead of just restricting it to # the set in `self.formats`... fmts = set([ k.split('.', 2)[1] for k in self.settings.keys() if k.startswith('format.') and '.' in k[8:] ]) fmts -= set(['default', 'override']) for fmt in fmts: rndr = self.settings.get('format.' + fmt + '.renderer', None) if rndr: self.renderers[fmt] = rndr self.options[fmt] = extract(self.settings, 'format.' + fmt + '.default') self.override[fmt] = extract(self.settings, 'format.' + fmt + '.override') # load the entry/type/catalog parsers and filters stropts = dict(self.str_options) self.eparsers = asset.plugins( 'pyramid_describe.plugins.entry.parsers', self.settings.get('entry.parsers', stropts.get('entry.parsers'))) self.tparsers = asset.plugins( 'pyramid_describe.plugins.type.parsers', self.settings.get('type.parsers', stropts.get('type.parsers'))) self.cparsers = asset.plugins( 'pyramid_describe.plugins.catalog.parsers', self.settings.get('catalog.parsers', stropts.get('catalog.parsers'))) self.efilters = asset.plugins( 'pyramid_describe.plugins.entry.filters', self.settings.get('entry.filters', stropts.get('entry.filters'))) self.tfilters = asset.plugins( 'pyramid_describe.plugins.type.filters', self.settings.get('type.filters', stropts.get('type.filters'))) self.cfilters = asset.plugins( 'pyramid_describe.plugins.catalog.filters', self.settings.get('catalog.filters', stropts.get('catalog.filters'))) self.render_template = self.settings.get('render.template', None) self.methOrderKey = methOrderKey( tolist(self.settings.get('methods.order', DEFAULT_METHODS_ORDER))) tropts = morph.pick(self.settings, prefix='typereg.') tropts['commentToken'] = self.settings.get( 'commentToken', dict(self.str_options).get('commentToken')) self.typereg = TypeRegistry(tropts)
def e2j(self, entry): data = morph.pick(entry, *api.Entry.ATTRIBUTES) data['password'] = self.encrypt(data.get('password'), symmetric=True) return data