Add Manufacturer

This commit is contained in:
Xavier Bustamante Talavera 2018-09-30 19:40:28 +02:00
parent 042b7718ec
commit 38060d47ec
9 changed files with 2952 additions and 6 deletions

View file

@ -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)**.

View file

@ -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

View file

@ -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))

View file

@ -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

View file

@ -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)

View file

@ -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
)
)

View file

@ -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'])

View file

@ -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."""