Add Manufacturer
This commit is contained in:
parent
042b7718ec
commit
38060d47ec
|
@ -23,6 +23,9 @@ an ID and a tag provider. Note though that these virtual tags don't have
|
|||
to forcefully be printed or have a physical representation
|
||||
(this is not imposed at system level).
|
||||
|
||||
Tags are case insensitive and are converted to lower-case in
|
||||
Devicehub.
|
||||
|
||||
eTags
|
||||
*****
|
||||
We recognize a special type of tag, the **eReuse.org tags (eTag)**.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from teal.resource import Converters, Resource
|
||||
|
||||
from ereuse_devicehub.resources.device import schemas
|
||||
from ereuse_devicehub.resources.device.views import DeviceView
|
||||
from ereuse_devicehub.resources.device.models import Manufacturer
|
||||
from ereuse_devicehub.resources.device.views import DeviceView, ManufacturerView
|
||||
|
||||
|
||||
class DeviceDef(Resource):
|
||||
|
@ -119,3 +120,13 @@ class SoundCardDef(ComponentDef):
|
|||
class DisplayDef(ComponentDef):
|
||||
VIEW = None
|
||||
SCHEMA = schemas.Display
|
||||
|
||||
|
||||
class ManufacturerDef(Resource):
|
||||
VIEW = ManufacturerView
|
||||
SCHEMA = schemas.Manufacturer
|
||||
AUTH = True
|
||||
|
||||
def init_db(self, db: 'db.SQLAlchemy'):
|
||||
"""Loads the manufacturers to the database."""
|
||||
Manufacturer.add_all_to_session(db.session)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,12 @@
|
|||
import json
|
||||
import pathlib
|
||||
from contextlib import suppress
|
||||
from itertools import chain
|
||||
from operator import attrgetter
|
||||
from typing import Dict, Set
|
||||
|
||||
from boltons import urlutils
|
||||
from citext import CIText
|
||||
from ereuse_utils.naming import Naming
|
||||
from sqlalchemy import BigInteger, Boolean, Column, Enum as DBEnum, Float, ForeignKey, Integer, \
|
||||
Sequence, SmallInteger, Unicode, inspect
|
||||
|
@ -11,10 +15,11 @@ from sqlalchemy.orm import ColumnProperty, backref, relationship, validates
|
|||
from sqlalchemy.util import OrderedSet
|
||||
from sqlalchemy_utils import ColorType
|
||||
from stdnum import imei, meid
|
||||
from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, check_lower, \
|
||||
from teal.db import CASCADE, POLYMORPHIC_ID, POLYMORPHIC_ON, ResourceNotFound, URL, check_lower, \
|
||||
check_range
|
||||
from teal.marshmallow import ValidationError
|
||||
|
||||
from ereuse_devicehub.db import db
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \
|
||||
RamFormat, RamInterface
|
||||
from ereuse_devicehub.resources.models import STR_SM_SIZE, Thing
|
||||
|
@ -316,3 +321,25 @@ class Display(JoinedComponentTableMixin, DisplayMixin, Component):
|
|||
and Television Set.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Manufacturer(db.Model):
|
||||
__table_args__ = {'schema': 'common'}
|
||||
CUSTOM_MANUFACTURERS = {'Belinea', 'OKI Data Corporation', 'Vivitek', 'Yuraku'}
|
||||
"""A list of manufacturer names that are not from Wikipedia's JSON."""
|
||||
|
||||
name = db.Column(CIText(), primary_key=True)
|
||||
url = db.Column(URL(), unique=True)
|
||||
logo = db.Column(URL())
|
||||
|
||||
@classmethod
|
||||
def add_all_to_session(cls, session):
|
||||
"""Adds all manufacturers to session."""
|
||||
with pathlib.Path(__file__).parent.joinpath('manufacturers.json').open() as f:
|
||||
for m in json.load(f):
|
||||
man = cls(name=m['name'],
|
||||
url=urlutils.URL(m['url']),
|
||||
logo=urlutils.URL(m['logo']) if m.get('logo', None) else None)
|
||||
session.add(man)
|
||||
for name in cls.CUSTOM_MANUFACTURERS:
|
||||
session.add(cls(name=name))
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
from typing import Dict, List, Set
|
||||
|
||||
from boltons.urlutils import URL
|
||||
from colour import Color
|
||||
from sqlalchemy import Column, Integer
|
||||
from sqlalchemy.orm import relationship
|
||||
from teal.db import Model
|
||||
|
||||
from ereuse_devicehub.resources.enums import ComputerChassis, DataStorageInterface, DisplayTech, \
|
||||
RamFormat, RamInterface
|
||||
|
@ -210,3 +212,20 @@ class RamModule(Component):
|
|||
|
||||
class Display(DisplayMixin, Component):
|
||||
pass
|
||||
|
||||
|
||||
class Manufacturer(Model):
|
||||
CUSTOM_MANUFACTURERS = ... # type: set
|
||||
name = ... # type: Column
|
||||
url = ... # type: Column
|
||||
logo = ... # type: Column
|
||||
|
||||
def __init__(self, **kwargs) -> None:
|
||||
super().__init__()
|
||||
self.name = ... # type: str
|
||||
self.url = ... # type: URL
|
||||
self.logo = ... # type: URL
|
||||
|
||||
@classmethod
|
||||
def add_all_to_session(cls, session):
|
||||
pass
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from marshmallow import post_load, pre_load
|
||||
from marshmallow.fields import Boolean, Float, Integer, Str
|
||||
from marshmallow.fields import Boolean, Float, Integer, Str, String
|
||||
from marshmallow.validate import Length, OneOf, Range
|
||||
from sqlalchemy.util import OrderedSet
|
||||
from stdnum import imei, meid
|
||||
from teal.marshmallow import EnumField, SanitizedStr, ValidationError
|
||||
from teal.marshmallow import EnumField, SanitizedStr, URL, ValidationError
|
||||
from teal.resource import Schema
|
||||
|
||||
from ereuse_devicehub.marshmallow import NestedOn
|
||||
from ereuse_devicehub.resources.device import models as m
|
||||
|
@ -183,3 +184,9 @@ class SoundCard(Component):
|
|||
|
||||
class Display(DisplayMixin, Component):
|
||||
pass
|
||||
|
||||
|
||||
class Manufacturer(Schema):
|
||||
name = String(dump_only=True)
|
||||
url = URL(dump_only=True)
|
||||
logo = URL(dump_only=True)
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import marshmallow
|
||||
from flask import current_app as app
|
||||
from flask.json import jsonify
|
||||
from flask_sqlalchemy import Pagination
|
||||
from teal.resource import View
|
||||
|
||||
from ereuse_devicehub.resources.device.models import Device
|
||||
from ereuse_devicehub.resources.device.models import Device, Manufacturer
|
||||
|
||||
|
||||
class DeviceView(View):
|
||||
|
@ -29,3 +33,23 @@ class DeviceView(View):
|
|||
def find(self, args: dict):
|
||||
"""Gets many devices."""
|
||||
return self.schema.jsonify(Device.query, many=True)
|
||||
|
||||
|
||||
class ManufacturerView(View):
|
||||
class FindArgs(marshmallow.Schema):
|
||||
name = marshmallow.fields.Str(required=True,
|
||||
# Disallow like operators
|
||||
validate=lambda x: '%' not in x and '_' not in x)
|
||||
|
||||
def find(self, args: dict):
|
||||
name = args['name']
|
||||
manufacturers = Manufacturer.query \
|
||||
.filter(Manufacturer.name.ilike(name + '%')) \
|
||||
.paginate(page=1, per_page=6) # type: Pagination
|
||||
return jsonify(
|
||||
items=app.resources[Manufacturer.t].schema.dump(
|
||||
manufacturers.items,
|
||||
many=True,
|
||||
nested=1
|
||||
)
|
||||
)
|
||||
|
|
|
@ -26,6 +26,7 @@ def test_api_docs(client: Client):
|
|||
'/users/login',
|
||||
'/events/',
|
||||
'/lots/',
|
||||
'/manufacturers/',
|
||||
'/lots/{id}/children',
|
||||
'/lots/{id}/devices',
|
||||
'/tags/{tag_id}/device/{device_id}'
|
||||
|
@ -39,4 +40,4 @@ def test_api_docs(client: Client):
|
|||
'scheme': 'basic',
|
||||
'name': 'Authorization'
|
||||
}
|
||||
assert 77 == len(docs['definitions'])
|
||||
assert 78 == len(docs['definitions'])
|
||||
|
|
|
@ -467,3 +467,14 @@ def test_device_search_all_devices_token_if_empty(app: Devicehub, user: UserClie
|
|||
DeviceSearch.set_all_devices_tokens_if_empty(app.db.session)
|
||||
i, _ = user.get(res=Inventory, query=[('search', 'Desktop')])
|
||||
assert not len(i['devices'])
|
||||
|
||||
|
||||
def test_manufacturer(user: UserClient):
|
||||
m, _ = user.get(res='Manufacturer', query=[('name', 'asus')])
|
||||
assert m == {'items': [{'name': 'Asus', 'url': 'https://en.wikipedia.org/wiki/Asus'}]}
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason='Develop functionality')
|
||||
def test_manufacturer_enforced():
|
||||
"""Ensures that non-computer devices can submit only
|
||||
manufacturers from the Manufacturer table."""
|
||||
|
|
Reference in New Issue