resource/asset normalization
| | |
| | | pyramid.traversal.ModelGraphTraverser -> |
| | | pyramid.traversal.ResourceTreeTraverser |
| | | |
| | | pyramid.traversal.ModelGraphTraverser -> |
| | | pyramid.traversal.ResourceTreeTraverser |
| | | |
| | | pyramid.config.Configurator.testing_models -> |
| | | pyramid.config.Configurator.testing_resources |
| | | |
| | | pyramid.request.Request.model_url -> |
| | | pyramid.request.Request.resource_url |
| | | |
| | | pyramid.testing.registerModels -> |
| | | pyramid.testing.registerResources |
| | |
| | | |
| | | .. automethod:: maybe_dotted |
| | | |
| | | .. automethod:: absolute_resource_spec |
| | | .. automethod:: absolute_asset_spec |
| | | |
| | | .. automethod:: setup_registry(settings=None, root_factory=None, authentication_policy=None, renderers=DEFAULT_RENDERERS, debug_logger=None, locale_negotiator=None, request_factory=None, renderer_globals_factory=None) |
| | | |
| | |
| | | |
| | | .. automethod:: make_wsgi_app() |
| | | |
| | | .. automethod:: override_resource(to_override, override_with) |
| | | .. automethod:: override_asset(to_override, override_with) |
| | | |
| | | .. automethod:: scan(package=None, categories=None) |
| | | |
| | |
| | | Python 2.5.4 (r254:67916, Sep 4 2009, 02:12:16) |
| | | [GCC 4.2.1 (Apple Inc. build 5646)] on darwin |
| | | Type "help" for more information. "root" is the Pyramid app root object. |
| | | >>> from pyramid.traversal import model_path |
| | | >>> from pyramid.traversal import resource_path |
| | | >>> from myapp.models import Document |
| | | >>> root['name'] = Document('title') |
| | | >>> doc = root['name'] |
| | | >>> docid = root.catalog.document_map.add(model_path(doc)) |
| | | >>> docid = root.catalog.document_map.add(resource_path(doc)) |
| | | >>> root.catalog.index_doc(docid, doc) |
| | | >>> import transaction |
| | | >>> transaction.commit() |
| | |
| | | The ``view_wiki`` view function |
| | | ------------------------------- |
| | | |
| | | The ``view_wiki`` function will be configured to respond as the |
| | | default view of a ``Wiki`` model object. It always redirects to the |
| | | ``Page`` object named "FrontPage". It returns an instance of the |
| | | :class:`pyramid.httpexceptions.HTTPFound` class (instances of which |
| | | implement the WebOb :term:`response` interface), and the |
| | | :func:`pyramid.url.model_url` API. :func:`pyramid.url.model_url` |
| | | constructs a URL to the ``FrontPage`` page |
| | | (e.g. ``http://localhost:6543/FrontPage``), and uses it as the |
| | | "location" of the HTTPFound response, forming an HTTP redirect. |
| | | The ``view_wiki`` function will be configured to respond as the default view |
| | | of a ``Wiki`` model object. It always redirects to the ``Page`` object named |
| | | "FrontPage". It returns an instance of the |
| | | :class:`pyramid.httpexceptions.HTTPFound` class (instances of which implement |
| | | the WebOb :term:`response` interface), and the |
| | | :func:`pyramid.url.resource_url` API. :func:`pyramid.url.resource_url` |
| | | constructs a URL to the ``FrontPage`` page resource |
| | | (e.g. ``http://localhost:6543/FrontPage``), and uses it as the "location" of |
| | | the HTTPFound response, forming an HTTP redirect. |
| | | |
| | | The ``view_page`` view function |
| | | ------------------------------- |
| | |
| | | from pyramid.httpexceptions import HTTPFound |
| | | |
| | | from pyramid.view import view_config |
| | | from pyramid.url import model_url |
| | | from pyramid.url import resource_url |
| | | |
| | | from pyramid.security import remember |
| | | from pyramid.security import forget |
| | |
| | | |
| | | @view_config(context=Wiki, name='login', renderer='templates/login.pt') |
| | | def login(request): |
| | | login_url = model_url(request.context, request, 'login') |
| | | login_url = resource_url(request.context, request, 'login') |
| | | referrer = request.url |
| | | if referrer == login_url: |
| | | referrer = '/' # never use the login form itself as came_from |
| | |
| | | @view_config(context=Wiki, name='logout') |
| | | def logout(request): |
| | | headers = forget(request) |
| | | return HTTPFound(location = model_url(request.context, request), |
| | | return HTTPFound(location = resource_url(request.context, request), |
| | | headers = headers) |
| | | |
| | |
| | | class ViewWikiTests(unittest.TestCase): |
| | | def test_it(self): |
| | | from tutorial.views import view_wiki |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | response = view_wiki(context, request) |
| | | self.assertEqual(response.location, 'http://example.com/FrontPage') |
| | |
| | | return view_page(context, request) |
| | | |
| | | def test_it(self): |
| | | wiki = testing.DummyModel() |
| | | wiki['IDoExist'] = testing.DummyModel() |
| | | context = testing.DummyModel(data='Hello CruelWorld IDoExist') |
| | | wiki = testing.DummyResource() |
| | | wiki['IDoExist'] = testing.DummyResource() |
| | | context = testing.DummyResource(data='Hello CruelWorld IDoExist') |
| | | context.__parent__ = wiki |
| | | context.__name__ = 'thepage' |
| | | request = testing.DummyRequest() |
| | |
| | | return add_page(context, request) |
| | | |
| | | def test_it_notsubmitted(self): |
| | | from pyramid.url import model_url |
| | | context = testing.DummyModel() |
| | | from pyramid.url import resource_url |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | request.subpath = ['AnotherPage'] |
| | | info = self._callFUT(context, request) |
| | | self.assertEqual(info['page'].data,'') |
| | | self.assertEqual(info['save_url'], |
| | | model_url(context, request, 'add_page', 'AnotherPage')) |
| | | resource_url( |
| | | context, request, 'add_page', 'AnotherPage')) |
| | | |
| | | def test_it_submitted(self): |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest({'form.submitted':True, |
| | | 'body':'Hello yo!'}) |
| | | request.subpath = ['AnotherPage'] |
| | |
| | | return edit_page(context, request) |
| | | |
| | | def test_it_notsubmitted(self): |
| | | from pyramid.url import model_url |
| | | context = testing.DummyModel() |
| | | from pyramid.url import resource_url |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | info = self._callFUT(context, request) |
| | | self.assertEqual(info['page'], context) |
| | | self.assertEqual(info['save_url'], |
| | | model_url(context, request, 'edit_page')) |
| | | resource_url(context, request, 'edit_page')) |
| | | |
| | | def test_it_submitted(self): |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest({'form.submitted':True, |
| | | 'body':'Hello yo!'}) |
| | | response = self._callFUT(context, request) |
| | |
| | | import re |
| | | |
| | | from pyramid.httpexceptions import HTTPFound |
| | | from pyramid.url import model_url |
| | | from pyramid.url import resource_url |
| | | |
| | | from pyramid.security import authenticated_userid |
| | | |
| | |
| | | |
| | | @view_config(context=Wiki, permission='view') |
| | | def view_wiki(context, request): |
| | | return HTTPFound(location = model_url(context, request, 'FrontPage')) |
| | | return HTTPFound(location = resource_url(context, request, 'FrontPage')) |
| | | |
| | | @view_config(context=Page, renderer='templates/view.pt', permission='view') |
| | | def view_page(context, request): |
| | |
| | | word = match.group(1) |
| | | if word in wiki: |
| | | page = wiki[word] |
| | | view_url = model_url(page, request) |
| | | view_url = resource_url(page, request) |
| | | return '<a href="%s">%s</a>' % (view_url, word) |
| | | else: |
| | | add_url = request.application_url + '/add_page/' + word |
| | |
| | | |
| | | content = publish_parts(context.data, writer_name='html')['html_body'] |
| | | content = wikiwords.sub(check, content) |
| | | edit_url = model_url(context, request, 'edit_page') |
| | | edit_url = resource_url(context, request, 'edit_page') |
| | | |
| | | logged_in = authenticated_userid(request) |
| | | |
| | |
| | | page.__name__ = name |
| | | page.__parent__ = context |
| | | context[name] = page |
| | | return HTTPFound(location = model_url(page, request)) |
| | | save_url = model_url(context, request, 'add_page', name) |
| | | return HTTPFound(location = resource_url(page, request)) |
| | | save_url = resource_url(context, request, 'add_page', name) |
| | | page = Page('') |
| | | page.__name__ = name |
| | | page.__parent__ = context |
| | |
| | | def edit_page(context, request): |
| | | if 'form.submitted' in request.params: |
| | | context.data = request.params['body'] |
| | | return HTTPFound(location = model_url(context, request)) |
| | | return HTTPFound(location = resource_url(context, request)) |
| | | |
| | | logged_in = authenticated_userid(request) |
| | | |
| | | return dict(page = context, |
| | | save_url = model_url(context, request, 'edit_page'), |
| | | save_url = resource_url(context, request, 'edit_page'), |
| | | logged_in = logged_in) |
| | | |
| | |
| | | class ViewWikiTests(unittest.TestCase): |
| | | def test_it(self): |
| | | from tutorial.views import view_wiki |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | response = view_wiki(context, request) |
| | | self.assertEqual(response.location, 'http://example.com/FrontPage') |
| | |
| | | return view_page(context, request) |
| | | |
| | | def test_it(self): |
| | | wiki = testing.DummyModel() |
| | | wiki['IDoExist'] = testing.DummyModel() |
| | | context = testing.DummyModel(data='Hello CruelWorld IDoExist') |
| | | wiki = testing.DummyResource() |
| | | wiki['IDoExist'] = testing.DummyResource() |
| | | context = testing.DummyResource(data='Hello CruelWorld IDoExist') |
| | | context.__parent__ = wiki |
| | | context.__name__ = 'thepage' |
| | | request = testing.DummyRequest() |
| | |
| | | return add_page(context, request) |
| | | |
| | | def test_it_notsubmitted(self): |
| | | from pyramid.url import model_url |
| | | context = testing.DummyModel() |
| | | from pyramid.url import resource_url |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | request.subpath = ['AnotherPage'] |
| | | info = self._callFUT(context, request) |
| | | self.assertEqual(info['page'].data,'') |
| | | self.assertEqual(info['save_url'], |
| | | model_url(context, request, 'add_page', 'AnotherPage')) |
| | | resource_url( |
| | | context, request, 'add_page', 'AnotherPage')) |
| | | |
| | | def test_it_submitted(self): |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest({'form.submitted':True, |
| | | 'body':'Hello yo!'}) |
| | | request.subpath = ['AnotherPage'] |
| | |
| | | return edit_page(context, request) |
| | | |
| | | def test_it_notsubmitted(self): |
| | | from pyramid.url import model_url |
| | | context = testing.DummyModel() |
| | | from pyramid.url import resource_url |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | info = self._callFUT(context, request) |
| | | self.assertEqual(info['page'], context) |
| | | self.assertEqual(info['save_url'], |
| | | model_url(context, request, 'edit_page')) |
| | | resource_url(context, request, 'edit_page')) |
| | | |
| | | def test_it_submitted(self): |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest({'form.submitted':True, |
| | | 'body':'Hello yo!'}) |
| | | response = self._callFUT(context, request) |
| | |
| | | import re |
| | | |
| | | from pyramid.httpexceptions import HTTPFound |
| | | from pyramid.url import model_url |
| | | from pyramid.url import resource_url |
| | | from pyramid.view import view_config |
| | | |
| | | from tutorial.models import Page |
| | |
| | | |
| | | @view_config(context=Wiki) |
| | | def view_wiki(context, request): |
| | | return HTTPFound(location = model_url(context, request, 'FrontPage')) |
| | | return HTTPFound(location = resource_url(context, request, 'FrontPage')) |
| | | |
| | | @view_config(context=Page, renderer='templates/view.pt') |
| | | def view_page(context, request): |
| | |
| | | word = match.group(1) |
| | | if word in wiki: |
| | | page = wiki[word] |
| | | view_url = model_url(page, request) |
| | | view_url = resource_url(page, request) |
| | | return '<a href="%s">%s</a>' % (view_url, word) |
| | | else: |
| | | add_url = request.application_url + '/add_page/' + word |
| | |
| | | |
| | | content = publish_parts(context.data, writer_name='html')['html_body'] |
| | | content = wikiwords.sub(check, content) |
| | | edit_url = model_url(context, request, 'edit_page') |
| | | edit_url = resource_url(context, request, 'edit_page') |
| | | return dict(page = context, content = content, edit_url = edit_url) |
| | | |
| | | @view_config(context=Wiki, name='add_page', renderer='templates/edit.pt') |
| | |
| | | page.__name__ = name |
| | | page.__parent__ = context |
| | | context[name] = page |
| | | return HTTPFound(location = model_url(page, request)) |
| | | save_url = model_url(context, request, 'add_page', name) |
| | | return HTTPFound(location = resource_url(page, request)) |
| | | save_url = resource_url(context, request, 'add_page', name) |
| | | page = Page('') |
| | | page.__name__ = name |
| | | page.__parent__ = context |
| | |
| | | def edit_page(context, request): |
| | | if 'form.submitted' in request.params: |
| | | context.data = request.params['body'] |
| | | return HTTPFound(location = model_url(context, request)) |
| | | return HTTPFound(location = resource_url(context, request)) |
| | | |
| | | return dict(page = context, |
| | | save_url = model_url(context, request, 'edit_page')) |
| | | save_url = resource_url(context, request, 'edit_page')) |
| | | |
| | | |
| | |
| | | class ViewWikiTests(unittest.TestCase): |
| | | def test_it(self): |
| | | from tutorial.views import view_wiki |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | response = view_wiki(context, request) |
| | | self.assertEqual(response.location, 'http://example.com/FrontPage') |
| | |
| | | return view_page(context, request) |
| | | |
| | | def test_it(self): |
| | | wiki = testing.DummyModel() |
| | | wiki['IDoExist'] = testing.DummyModel() |
| | | context = testing.DummyModel(data='Hello CruelWorld IDoExist') |
| | | wiki = testing.DummyResource() |
| | | wiki['IDoExist'] = testing.DummyResource() |
| | | context = testing.DummyResource(data='Hello CruelWorld IDoExist') |
| | | context.__parent__ = wiki |
| | | context.__name__ = 'thepage' |
| | | request = testing.DummyRequest() |
| | |
| | | return add_page(context, request) |
| | | |
| | | def test_it_notsubmitted(self): |
| | | from pyramid.url import model_url |
| | | context = testing.DummyModel() |
| | | from pyramid.url import resource_url |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | request.subpath = ['AnotherPage'] |
| | | info = self._callFUT(context, request) |
| | | self.assertEqual(info['page'].data,'') |
| | | self.assertEqual( |
| | | info['save_url'], |
| | | model_url(context, request, 'add_page', 'AnotherPage')) |
| | | resource_url(context, request, 'add_page', 'AnotherPage')) |
| | | |
| | | def test_it_submitted(self): |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest({'form.submitted':True, |
| | | 'body':'Hello yo!'}) |
| | | request.subpath = ['AnotherPage'] |
| | |
| | | return edit_page(context, request) |
| | | |
| | | def test_it_notsubmitted(self): |
| | | from pyramid.url import model_url |
| | | context = testing.DummyModel() |
| | | from pyramid.url import resource_url |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest() |
| | | info = self._callFUT(context, request) |
| | | self.assertEqual(info['page'], context) |
| | | self.assertEqual(info['save_url'], |
| | | model_url(context, request, 'edit_page')) |
| | | resource_url(context, request, 'edit_page')) |
| | | |
| | | def test_it_submitted(self): |
| | | context = testing.DummyModel() |
| | | context = testing.DummyResource() |
| | | request = testing.DummyRequest({'form.submitted':True, |
| | | 'body':'Hello yo!'}) |
| | | response = self._callFUT(context, request) |
| | |
| | | import re |
| | | |
| | | from pyramid.httpexceptions import HTTPFound |
| | | from pyramid.url import model_url |
| | | from pyramid.url import resource_url |
| | | |
| | | from tutorial.models import Page |
| | | |
| | |
| | | wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)") |
| | | |
| | | def view_wiki(context, request): |
| | | return HTTPFound(location = model_url(context, request, 'FrontPage')) |
| | | return HTTPFound(location = resource_url(context, request, 'FrontPage')) |
| | | |
| | | def view_page(context, request): |
| | | wiki = context.__parent__ |
| | |
| | | word = match.group(1) |
| | | if word in wiki: |
| | | page = wiki[word] |
| | | view_url = model_url(page, request) |
| | | view_url = resource_url(page, request) |
| | | return '<a href="%s">%s</a>' % (view_url, word) |
| | | else: |
| | | add_url = request.application_url + '/add_page/' + word |
| | |
| | | |
| | | content = publish_parts(context.data, writer_name='html')['html_body'] |
| | | content = wikiwords.sub(check, content) |
| | | edit_url = model_url(context, request, 'edit_page') |
| | | edit_url = resource_url(context, request, 'edit_page') |
| | | return dict(page = context, content = content, edit_url = edit_url) |
| | | |
| | | def add_page(context, request): |
| | |
| | | page.__name__ = name |
| | | page.__parent__ = context |
| | | context[name] = page |
| | | return HTTPFound(location = model_url(page, request)) |
| | | save_url = model_url(context, request, 'add_page', name) |
| | | return HTTPFound(location = resource_url(page, request)) |
| | | save_url = resource_url(context, request, 'add_page', name) |
| | | page = Page('') |
| | | page.__name__ = name |
| | | page.__parent__ = context |
| | |
| | | def edit_page(context, request): |
| | | if 'form.submitted' in request.params: |
| | | context.data = request.params['body'] |
| | | return HTTPFound(location = model_url(context, request)) |
| | | return HTTPFound(location = resource_url(context, request)) |
| | | |
| | | return dict(page = context, |
| | | save_url = model_url(context, request, 'edit_page')) |
| | | save_url = resource_url(context, request, 'edit_page')) |
| | | |
| | | |
| | |
| | | self.assertEqual(ut.groupids, ('group1', 'group2')) |
| | | self.assertEqual(ut.permissive, False) |
| | | |
| | | def test_testing_models(self): |
| | | from pyramid.traversal import find_model |
| | | def test_testing_resources(self): |
| | | from pyramid.traversal import find_resource |
| | | from pyramid.interfaces import ITraverser |
| | | ob1 = object() |
| | | ob2 = object() |
| | | models = {'/ob1':ob1, '/ob2':ob2} |
| | | resources = {'/ob1':ob1, '/ob2':ob2} |
| | | config = self._makeOne(autocommit=True) |
| | | config.testing_models(models) |
| | | config.testing_resources(resources) |
| | | adapter = config.registry.getAdapter(None, ITraverser) |
| | | result = adapter({'PATH_INFO':'/ob1'}) |
| | | self.assertEqual(result['context'], ob1) |
| | |
| | | self.assertRaises(KeyError, adapter, {'PATH_INFO':'/ob3'}) |
| | | try: |
| | | config.begin() |
| | | self.assertEqual(find_model(None, '/ob1'), ob1) |
| | | self.assertEqual(find_resource(None, '/ob1'), ob1) |
| | | finally: |
| | | config.end() |
| | | |
| | |
| | | self.assertEqual(result['reload_templates'], True) |
| | | |
| | | def test_reload_resources(self): |
| | | # alias for reload_assets |
| | | result = self._makeOne({}) |
| | | self.assertEqual(result['reload_resources'], False) |
| | | self.assertEqual(result['reload_assets'], False) |
| | | result = self._makeOne({'reload_resources':'false'}) |
| | | self.assertEqual(result['reload_resources'], False) |
| | | self.assertEqual(result['reload_assets'], False) |
| | | result = self._makeOne({'reload_resources':'t'}) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | result = self._makeOne({'reload_resources':'1'}) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | result = self._makeOne({}, {'BFG_RELOAD_RESOURCES':'1'}) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | result = self._makeOne({'reload_resources':'false'}, |
| | | {'BFG_RELOAD_RESOURCES':'1'}) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | |
| | | def test_reload_assets(self): |
| | | # alias for reload_resources |
| | | result = self._makeOne({}) |
| | | self.assertEqual(result['reload_assets'], False) |
| | | self.assertEqual(result['reload_resources'], False) |
| | | result = self._makeOne({'reload_assets':'false'}) |
| | | self.assertEqual(result['reload_resources'], False) |
| | | self.assertEqual(result['reload_assets'], False) |
| | | result = self._makeOne({'reload_assets':'t'}) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | result = self._makeOne({'reload_assets':'1'}) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | result = self._makeOne({}, {'BFG_RELOAD_ASSETS':'1'}) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | result = self._makeOne({'reload_assets':'false'}, |
| | | {'BFG_RELOAD_ASSETS':'1'}) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | |
| | | |
| | | def test_reload_all(self): |
| | | result = self._makeOne({}) |
| | | self.assertEqual(result['reload_templates'], False) |
| | | self.assertEqual(result['reload_resources'], False) |
| | | self.assertEqual(result['reload_assets'], False) |
| | | result = self._makeOne({'reload_all':'false'}) |
| | | self.assertEqual(result['reload_templates'], False) |
| | | self.assertEqual(result['reload_resources'], False) |
| | | self.assertEqual(result['reload_assets'], False) |
| | | result = self._makeOne({'reload_all':'t'}) |
| | | self.assertEqual(result['reload_templates'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | result = self._makeOne({'reload_all':'1'}) |
| | | self.assertEqual(result['reload_templates'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | result = self._makeOne({}, {'BFG_RELOAD_ALL':'1'}) |
| | | self.assertEqual(result['reload_templates'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | result = self._makeOne({'reload_all':'false'}, |
| | | {'BFG_RELOAD_ALL':'1'}) |
| | | self.assertEqual(result['reload_templates'], True) |
| | | self.assertEqual(result['reload_resources'], True) |
| | | self.assertEqual(result['reload_assets'], True) |
| | | |
| | | def test_debug_authorization(self): |
| | | result = self._makeOne({}) |