From 936c042c6201f720369b9651fbc0282f94e5b0fb Mon Sep 17 00:00:00 2001 From: nad Date: Thu, 23 Jul 2020 20:55:27 +0200 Subject: [PATCH 01/12] Creating document stock endpoint --- .../resources/documents/documents.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ereuse_devicehub/resources/documents/documents.py b/ereuse_devicehub/resources/documents/documents.py index e95a9694..3b148362 100644 --- a/ereuse_devicehub/resources/documents/documents.py +++ b/ereuse_devicehub/resources/documents/documents.py @@ -126,6 +126,29 @@ class DevicesDocumentView(DeviceView): return output +class StockDocumentView(DeviceView): + # @cache(datetime.timedelta(minutes=1)) + def find(self, args: dict): + query = self.query(args) + return self.generate_post_csv(query) + + def generate_post_csv(self, query): + """Get device query and put information in csv format.""" + data = StringIO() + cw = csv.writer(data) + first = True + for device in query: + d = DeviceRow(device) + if first: + cw.writerow(d.keys()) + first = False + cw.writerow(d.values()) + output = make_response(data.getvalue()) + output.headers['Content-Disposition'] = 'attachment; filename=export.csv' + output.headers['Content-type'] = 'text/csv' + return output + + class DocumentDef(Resource): __type__ = 'Document' SCHEMA = None @@ -156,6 +179,10 @@ class DocumentDef(Resource): devices_view = DevicesDocumentView.as_view('devicesDocumentView', definition=self, auth=app.auth) + + stock_view = StockDocumentView.as_view('stockDocumentView', definition=self) + if self.AUTH: devices_view = app.auth.requires_auth(devices_view) self.add_url_rule('/devices/', defaults=d, view_func=devices_view, methods=get) + self.add_url_rule('/stock/', defaults=d, view_func=stock_view, methods=get) From c90fa4e84eb346183460b692092000af38f98656 Mon Sep 17 00:00:00 2001 From: nad Date: Mon, 27 Jul 2020 13:56:56 +0200 Subject: [PATCH 02/12] Adding stock row class for new document endpoint --- .../resources/documents/device_row.py | 50 +++++++++++++++++-- .../resources/documents/documents.py | 7 +-- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/ereuse_devicehub/resources/documents/device_row.py b/ereuse_devicehub/resources/documents/device_row.py index dea1e698..6ba3b4c3 100644 --- a/ereuse_devicehub/resources/documents/device_row.py +++ b/ereuse_devicehub/resources/documents/device_row.py @@ -51,10 +51,6 @@ class DeviceRow(OrderedDict): self['Processor'] = device.processor_model self['RAM (MB)'] = device.ram_size self['Data Storage Size (MB)'] = device.data_storage_size - if isinstance(device, d.Mobile): - self['Display Size'] = device.display_size - self['RAM (MB)'] = device.ram_size - self['Data Storage Size (MB)'] = device.data_storage_size rate = device.rate if rate: self['Rate'] = rate.rating @@ -135,3 +131,49 @@ class DeviceRow(OrderedDict): self['{} {} Speed (MHz)'.format(type, i)] = component.speed # todo add Display, NetworkAdapter, etc... + + +class StockRow(OrderedDict): + def __init__(self, device: d.Device) -> None: + super().__init__() + self.device = device + self['Type'] = device.t + if isinstance(device, d.Computer): + self['Chassis'] = device.chassis + else: + self['Chassis'] = '' + self['Serial Number'] = device.serial_number + self['Model'] = device.model + self['Manufacturer'] = device.manufacturer + self['Registered in'] = format(device.created, '%c') + try: + self['Physical state'] = device.last_action_of(*states.Physical.actions()).t + except: + self['Physical state'] = '' + try: + self['Trading state'] = device.last_action_of(*states.Trading.actions()).t + except: + self['Trading state'] = '' + try: + self['Price'] = device.price + except: + self['Price'] = '' + try: + self['Processor'] = device.processor_model + self['RAM (MB)'] = device.ram_size + self['Data Storage Size (MB)'] = device.data_storage_size + except: + self['Processor'] = '' + self['RAM (MB)'] = '' + self['Data Storage Size (MB)'] = '' + rate = device.rate + if rate: + self['Rate'] = rate.rating + self['Range'] = rate.rating_range + assert isinstance(rate, RateComputer) + self['Processor Rate'] = rate.processor + self['Processor Range'] = rate.processor_range + self['RAM Rate'] = rate.ram + self['RAM Range'] = rate.ram_range + self['Data Storage Rate'] = rate.data_storage + self['Data Storage Range'] = rate.data_storage_range diff --git a/ereuse_devicehub/resources/documents/documents.py b/ereuse_devicehub/resources/documents/documents.py index 3b148362..641532ab 100644 --- a/ereuse_devicehub/resources/documents/documents.py +++ b/ereuse_devicehub/resources/documents/documents.py @@ -18,7 +18,8 @@ from ereuse_devicehub.db import db from ereuse_devicehub.resources.action import models as evs from ereuse_devicehub.resources.device import models as devs from ereuse_devicehub.resources.device.views import DeviceView -from ereuse_devicehub.resources.documents.device_row import DeviceRow + +from ereuse_devicehub.resources.documents.device_row import DeviceRow, StockRow class Format(enum.Enum): @@ -138,13 +139,13 @@ class StockDocumentView(DeviceView): cw = csv.writer(data) first = True for device in query: - d = DeviceRow(device) + d = StockRow(device) if first: cw.writerow(d.keys()) first = False cw.writerow(d.values()) output = make_response(data.getvalue()) - output.headers['Content-Disposition'] = 'attachment; filename=export.csv' + output.headers['Content-Disposition'] = 'attachment; filename=stock.csv' output.headers['Content-type'] = 'text/csv' return output From 322af04ff9cbefb705714842ecc8f1b3f7135308 Mon Sep 17 00:00:00 2001 From: nad Date: Mon, 27 Jul 2020 13:57:31 +0200 Subject: [PATCH 03/12] Creating new test for device stock control --- tests/files/basic-stock.csv | 2 ++ tests/test_documents.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/files/basic-stock.csv diff --git a/tests/files/basic-stock.csv b/tests/files/basic-stock.csv new file mode 100644 index 00000000..f8cd616d --- /dev/null +++ b/tests/files/basic-stock.csv @@ -0,0 +1,2 @@ +Type ,Chassis ,Serial Number,Model,Manufacturer,Registered in ,Physical state,Trading state,Price,Processor,RAM (MB),Data Storage Size (MB),Rate,Range ,Processor Rate,Processor Range,RAM Rate,RAM Range,Data Storage Rate,Data Storage Range +Desktop,Microtower,d1s ,d1ml ,d1mr ,Tue Jul 2 10:35:10 2019, , , ,p1ml ,0 ,0 ,1.0 ,Very low,1.0 ,Very low ,1.0 ,Very low ,1.0 ,Very low \ No newline at end of file diff --git a/tests/test_documents.py b/tests/test_documents.py index 0b40bf23..37ca9c36 100644 --- a/tests/test_documents.py +++ b/tests/test_documents.py @@ -223,3 +223,31 @@ def test_export_multiple_different_devices(user: UserClient): del row[8] assert fixture_csv == export_csv + + +@pytest.mark.mvp +def test_report_devices_stock_control(user: UserClient): + """Test export device information in a csv file.""" + snapshot, _ = user.post(file('basic.snapshot'), res=Snapshot) + csv_str, _ = user.get(res=documents.DocumentDef.t, + item='stock/', + accept='text/csv', + query=[('filter', {'type': ['Computer']})]) + f = StringIO(csv_str) + obj_csv = csv.reader(f, f) + export_csv = list(obj_csv) + + # Open fixture csv and transform to list + with Path(__file__).parent.joinpath('files').joinpath('basic-stock.csv').open() as csv_file: + obj_csv = csv.reader(csv_file) + fixture_csv = list(obj_csv) + + assert isinstance(datetime.strptime(export_csv[1][5], '%c'), datetime), \ + 'Register in field is not a datetime' + + # Pop dates fields from csv lists to compare them + fixture_csv[1] = fixture_csv[1][:5] + fixture_csv[1][6:] + export_csv[1] = export_csv[1][:5] + export_csv[1][6:] + + assert fixture_csv[0] == export_csv[0], 'Headers are not equal' + assert fixture_csv[1] == export_csv[1], 'Computer information are not equal' From a052abc72d570a63c671c6a4288830839356a839 Mon Sep 17 00:00:00 2001 From: Jordi Nadeu Date: Wed, 5 Aug 2020 11:56:59 +0200 Subject: [PATCH 04/12] Minor fix indentation error --- ereuse_devicehub/resources/documents/documents.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ereuse_devicehub/resources/documents/documents.py b/ereuse_devicehub/resources/documents/documents.py index 842a945a..7373f91a 100644 --- a/ereuse_devicehub/resources/documents/documents.py +++ b/ereuse_devicehub/resources/documents/documents.py @@ -139,7 +139,7 @@ class StockDocumentView(DeviceView): cw = csv.writer(data) first = True for device in query: - d = StockRow(device) + d = StockRow(device) if first: cw.writerow(d.keys()) first = False From f424309c174be7f13ddd484cc3167858ec5c1b6c Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 5 Aug 2020 12:22:06 +0200 Subject: [PATCH 05/12] add second user as user2 in features in conftest --- tests/conftest.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index bd6209ed..12682f1f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -93,6 +93,18 @@ def user(app: Devicehub) -> UserClient: return client +@pytest.fixture() +def user2(app: Devicehub) -> UserClient: + """Gets a client with a logged-in dummy user.""" + with app.app_context(): + password = 'foo' + email = 'foo2@foo.com' + user = create_user(email=email, password=password) + client = UserClient(app, user.email, password, response_wrapper=app.response_class) + client.login() + return client + + def create_user(email='foo@foo.com', password='foo') -> User: user = User(email=email, password=password) user.individuals.add(Person(name='Timmy')) From 96026caabbe802a15b7effef91e77db565a2b4db Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 5 Aug 2020 12:22:52 +0200 Subject: [PATCH 06/12] add new basic snapshot --- tests/files/basic.snapshot2.yaml | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 tests/files/basic.snapshot2.yaml diff --git a/tests/files/basic.snapshot2.yaml b/tests/files/basic.snapshot2.yaml new file mode 100644 index 00000000..7a444be9 --- /dev/null +++ b/tests/files/basic.snapshot2.yaml @@ -0,0 +1,34 @@ +type: Snapshot +uuid: 123e4567-e89b-12d3-a456-426655440000 +version: '11.0' +software: Workbench +elapsed: 4 +device: + type: Desktop + chassis: Microtower + serialNumber: d2s + model: d1ml + manufacturer: d1mr + actions: + - type: VisualTest + appearanceRange: A + functionalityRange: B +components: + - type: GraphicCard + serialNumber: gc1s + model: gc1ml + manufacturer: gc1mr + - type: RamModule + serialNumber: rm1s + model: rm1ml + manufacturer: rm1mr + speed: 1333 + - type: Processor + serialNumber: p1s + model: p1ml + manufacturer: p1mr + speed: 1.6 + actions: + - type: BenchmarkProcessor + rate: 2410 + elapsed: 11 From 19bff828735d6475e4531a7439adb7c32f3877d4 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 5 Aug 2020 12:23:24 +0200 Subject: [PATCH 07/12] fixing spaces in csv file --- tests/files/basic-stock.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/files/basic-stock.csv b/tests/files/basic-stock.csv index f8cd616d..d037b191 100644 --- a/tests/files/basic-stock.csv +++ b/tests/files/basic-stock.csv @@ -1,2 +1,2 @@ -Type ,Chassis ,Serial Number,Model,Manufacturer,Registered in ,Physical state,Trading state,Price,Processor,RAM (MB),Data Storage Size (MB),Rate,Range ,Processor Rate,Processor Range,RAM Rate,RAM Range,Data Storage Rate,Data Storage Range -Desktop,Microtower,d1s ,d1ml ,d1mr ,Tue Jul 2 10:35:10 2019, , , ,p1ml ,0 ,0 ,1.0 ,Very low,1.0 ,Very low ,1.0 ,Very low ,1.0 ,Very low \ No newline at end of file +Type,Chassis,Serial Number,Model,Manufacturer,Registered in,Physical state,Trading state,Price,Processor,RAM (MB),Data Storage Size (MB),Rate,Range,Processor Rate,Processor Range,RAM Rate,RAM Range,Data Storage Rate,Data Storage Range +Desktop,Microtower,d1s,d1ml,d1mr,Tue Jul 2 10:35:10 2019,,,,p1ml,0,0,1.0,Very low,1.0,Very low,1.0,Very low,1.0,Very low From 597ff3dc11c72fd13d3c8dd754963305e7d732fc Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Wed, 5 Aug 2020 12:24:36 +0200 Subject: [PATCH 08/12] add check of permissions --- tests/test_documents.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_documents.py b/tests/test_documents.py index 37ca9c36..8dd8f256 100644 --- a/tests/test_documents.py +++ b/tests/test_documents.py @@ -226,9 +226,11 @@ def test_export_multiple_different_devices(user: UserClient): @pytest.mark.mvp -def test_report_devices_stock_control(user: UserClient): +def test_report_devices_stock_control(user: UserClient, user2: UserClient): """Test export device information in a csv file.""" snapshot, _ = user.post(file('basic.snapshot'), res=Snapshot) + snapshot2, _ = user2.post(file('basic.snapshot2'), res=Snapshot) + csv_str, _ = user.get(res=documents.DocumentDef.t, item='stock/', accept='text/csv', @@ -242,6 +244,9 @@ def test_report_devices_stock_control(user: UserClient): obj_csv = csv.reader(csv_file) fixture_csv = list(obj_csv) + assert user.user['id'] != user2.user['id'] + assert len(export_csv) == 2 + assert isinstance(datetime.strptime(export_csv[1][5], '%c'), datetime), \ 'Register in field is not a datetime' From 801a8a6c4a3a9df1d20643542eb881cee8ce414a Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 6 Aug 2020 16:51:49 +0200 Subject: [PATCH 09/12] add filter as user owner --- ereuse_devicehub/resources/documents/documents.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/resources/documents/documents.py b/ereuse_devicehub/resources/documents/documents.py index 7373f91a..084fd6e4 100644 --- a/ereuse_devicehub/resources/documents/documents.py +++ b/ereuse_devicehub/resources/documents/documents.py @@ -10,7 +10,7 @@ import flask import flask_weasyprint import teal.marshmallow from boltons import urlutils -from flask import make_response +from flask import make_response, g from teal.cache import cache from teal.resource import Resource @@ -130,7 +130,7 @@ class DevicesDocumentView(DeviceView): class StockDocumentView(DeviceView): # @cache(datetime.timedelta(minutes=1)) def find(self, args: dict): - query = self.query(args) + query = (x for x in self.query(args) if x.owner_id==g.user.id) return self.generate_post_csv(query) def generate_post_csv(self, query): @@ -182,6 +182,7 @@ class DocumentDef(Resource): auth=app.auth) stock_view = StockDocumentView.as_view('stockDocumentView', definition=self) + stock_view = app.auth.requires_auth(stock_view) if self.AUTH: devices_view = app.auth.requires_auth(devices_view) From f97b239abe92a2ccde0d1c85ccc64a0743065717 Mon Sep 17 00:00:00 2001 From: Cayo Puigdefabregas Date: Thu, 6 Aug 2020 16:52:12 +0200 Subject: [PATCH 10/12] fixed bug diference model --- tests/files/basic.snapshot2.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/files/basic.snapshot2.yaml b/tests/files/basic.snapshot2.yaml index 7a444be9..70bfaa34 100644 --- a/tests/files/basic.snapshot2.yaml +++ b/tests/files/basic.snapshot2.yaml @@ -25,7 +25,7 @@ components: speed: 1333 - type: Processor serialNumber: p1s - model: p1ml + model: p1mla manufacturer: p1mr speed: 1.6 actions: From 59932ba00d6fa169058dd87e4caf67e00423ccfe Mon Sep 17 00:00:00 2001 From: nad Date: Mon, 17 Aug 2020 11:18:52 +0200 Subject: [PATCH 11/12] Adding exceptions to device_row.py file --- .../resources/documents/device_row.py | 56 +++++++++---------- .../resources/documents/documents.py | 3 +- tests/test_documents.py | 7 ++- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/ereuse_devicehub/resources/documents/device_row.py b/ereuse_devicehub/resources/documents/device_row.py index 6ba3b4c3..ecdc93d9 100644 --- a/ereuse_devicehub/resources/documents/device_row.py +++ b/ereuse_devicehub/resources/documents/device_row.py @@ -30,27 +30,23 @@ class DeviceRow(OrderedDict): self['Tag 1'] = self['Tag 2'] = self['Tag 3'] = '' for i, tag in zip(range(1, 3), device.tags): self['Tag {}'.format(i)] = format(tag) - self['Serial Number'] = device.serial_number - self['Model'] = device.model - self['Manufacturer'] = device.manufacturer - # self['State'] = device.last_action_of() + self['Serial Number'] = convert_none_to_empty_str(device.serial_number) + self['Model'] = convert_none_to_empty_str(device.model) + self['Manufacturer'] = convert_none_to_empty_str(device.manufacturer) self['Registered in'] = format(device.created, '%c') try: self['Physical state'] = device.last_action_of(*states.Physical.actions()).t - except: + except LookupError: self['Physical state'] = '' try: self['Trading state'] = device.last_action_of(*states.Trading.actions()).t - except: + except LookupError: self['Trading state'] = '' - try: - self['Price'] = device.price - except: - self['Price'] = '' + self['Price'] = convert_none_to_empty_str(device.price) if isinstance(device, d.Computer): - self['Processor'] = device.processor_model - self['RAM (MB)'] = device.ram_size - self['Data Storage Size (MB)'] = device.data_storage_size + self['Processor'] = convert_none_to_empty_str(device.processor_model) + self['RAM (MB)'] = convert_none_to_empty_str(device.ram_size) + self['Data Storage Size (MB)'] = convert_none_to_empty_str(device.data_storage_size) rate = device.rate if rate: self['Rate'] = rate.rating @@ -137,35 +133,27 @@ class StockRow(OrderedDict): def __init__(self, device: d.Device) -> None: super().__init__() self.device = device - self['Type'] = device.t + self['Type'] = convert_none_to_empty_str(device.t) if isinstance(device, d.Computer): self['Chassis'] = device.chassis else: self['Chassis'] = '' - self['Serial Number'] = device.serial_number - self['Model'] = device.model - self['Manufacturer'] = device.manufacturer + self['Serial Number'] = convert_none_to_empty_str(device.serial_number) + self['Model'] = convert_none_to_empty_str(device.model) + self['Manufacturer'] = convert_none_to_empty_str(device.manufacturer) self['Registered in'] = format(device.created, '%c') try: self['Physical state'] = device.last_action_of(*states.Physical.actions()).t - except: + except LookupError: self['Physical state'] = '' try: self['Trading state'] = device.last_action_of(*states.Trading.actions()).t - except: + except LookupError: self['Trading state'] = '' - try: - self['Price'] = device.price - except: - self['Price'] = '' - try: - self['Processor'] = device.processor_model - self['RAM (MB)'] = device.ram_size - self['Data Storage Size (MB)'] = device.data_storage_size - except: - self['Processor'] = '' - self['RAM (MB)'] = '' - self['Data Storage Size (MB)'] = '' + self['Price'] = convert_none_to_empty_str(device.price) + self['Processor'] = convert_none_to_empty_str(device.processor_model) + self['RAM (MB)'] = convert_none_to_empty_str(device.ram_size) + self['Data Storage Size (MB)'] = convert_none_to_empty_str(device.data_storage_size) rate = device.rate if rate: self['Rate'] = rate.rating @@ -177,3 +165,9 @@ class StockRow(OrderedDict): self['RAM Range'] = rate.ram_range self['Data Storage Rate'] = rate.data_storage self['Data Storage Range'] = rate.data_storage_range + + +def convert_none_to_empty_str(s): + if s is None: + return '' + return s diff --git a/ereuse_devicehub/resources/documents/documents.py b/ereuse_devicehub/resources/documents/documents.py index 084fd6e4..9fc1b06d 100644 --- a/ereuse_devicehub/resources/documents/documents.py +++ b/ereuse_devicehub/resources/documents/documents.py @@ -18,7 +18,6 @@ from ereuse_devicehub.db import db from ereuse_devicehub.resources.action import models as evs from ereuse_devicehub.resources.device import models as devs from ereuse_devicehub.resources.device.views import DeviceView - from ereuse_devicehub.resources.documents.device_row import DeviceRow, StockRow @@ -130,7 +129,7 @@ class DevicesDocumentView(DeviceView): class StockDocumentView(DeviceView): # @cache(datetime.timedelta(minutes=1)) def find(self, args: dict): - query = (x for x in self.query(args) if x.owner_id==g.user.id) + query = (x for x in self.query(args) if x.owner_id == g.user.id) return self.generate_post_csv(query) def generate_post_csv(self, query): diff --git a/tests/test_documents.py b/tests/test_documents.py index 8dd8f256..78476407 100644 --- a/tests/test_documents.py +++ b/tests/test_documents.py @@ -1,11 +1,12 @@ -import pytest -import teal.marshmallow -from ereuse_utils.test import ANY import csv from datetime import datetime from io import StringIO from pathlib import Path +import pytest +import teal.marshmallow +from ereuse_utils.test import ANY + from ereuse_devicehub.client import Client, UserClient from ereuse_devicehub.resources.action.models import Snapshot from ereuse_devicehub.resources.documents import documents From 65ba42ada80322624f5873a990f8c220592511a3 Mon Sep 17 00:00:00 2001 From: nad Date: Mon, 17 Aug 2020 15:57:27 +0200 Subject: [PATCH 12/12] Fixing test_documents.py::test_export_basic_snapshot and test_documents.py::test_export_full_snapshot --- ereuse_devicehub/resources/documents/documents.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ereuse_devicehub/resources/documents/documents.py b/ereuse_devicehub/resources/documents/documents.py index 700f916f..7533ed07 100644 --- a/ereuse_devicehub/resources/documents/documents.py +++ b/ereuse_devicehub/resources/documents/documents.py @@ -22,6 +22,7 @@ from ereuse_devicehub.resources.documents.device_row import DeviceRow, StockRow from flask import g, request + class Format(enum.Enum): HTML = 'HTML' PDF = 'PDF' @@ -107,7 +108,7 @@ class DocumentView(DeviceView): class DevicesDocumentView(DeviceView): @cache(datetime.timedelta(minutes=1)) def find(self, args: dict): - query = self.query(args) + query = (x for x in self.query(args) if x.owner_id == g.user.id) return self.generate_post_csv(query) def generate_post_csv(self, query): @@ -155,6 +156,7 @@ class DocumentDef(Resource): SCHEMA = None VIEW = None # We do not want to create default / documents endpoint AUTH = False + def __init__(self, app, import_name=__name__, static_folder='static', @@ -183,13 +185,11 @@ class DocumentDef(Resource): devices_view = DevicesDocumentView.as_view('devicesDocumentView', definition=self, auth=app.auth) + devices_view = app.auth.requires_auth(devices_view) stock_view = StockDocumentView.as_view('stockDocumentView', definition=self) stock_view = app.auth.requires_auth(stock_view) - if self.AUTH: - devices_view = app.auth.requires_auth(devices_view) - self.add_url_rule('/devices/', defaults=d, view_func=devices_view, methods=get) stock_view = StockDocumentView.as_view('stockDocumentView', definition=self, auth=app.auth)