Skip to content
This repository has been archived by the owner on Apr 23, 2024. It is now read-only.

Commit

Permalink
add tojson helper method (#163)
Browse files Browse the repository at this point in the history
  • Loading branch information
SebRut committed Mar 21, 2021
1 parent 4a33685 commit 7afc1b3
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 75 deletions.
16 changes: 13 additions & 3 deletions pygrocy/base.py
@@ -1,10 +1,20 @@
import json


def get_val(obj):
if hasattr(obj, 'as_dict'):
as_attr = getattr(obj, 'as_dict')
if hasattr(obj, "as_dict"):
as_attr = getattr(obj, "as_dict")
return as_attr()
return obj


class DataModel(object):
def toJson(self):
return json.dumps(self.as_dict())

def as_dict(self):
return {k: get_val(getattr(self, k)) for k, v in self.__class__.__dict__.items() if isinstance(v, property)}
return {
k: get_val(getattr(self, k))
for k, v in self.__class__.__dict__.items()
if isinstance(v, property)
}
13 changes: 11 additions & 2 deletions pygrocy/data_models/product.py
Expand Up @@ -7,13 +7,22 @@
GrocyApiClient,
LocationData,
MissingProductResponse,
ProductBarcode,
ProductBarcodeData,
ProductData,
ProductDetailsResponse,
ShoppingListItem,
)


class ProductBarcode(DataModel):
def __init__(self, data: ProductBarcodeData):
self._barcode = data.barcode

@property
def barcode(self) -> str:
return self._barcode


class Product(DataModel):
def __init__(self, data):
self._init_empty()
Expand Down Expand Up @@ -55,7 +64,7 @@ def _init_from_MissingProductResponse(self, response: MissingProductResponse):
def _init_from_ProductDetailsResponse(self, response: ProductDetailsResponse):
self._available_amount = response.stock_amount
self._best_before_date = response.next_best_before_date
self._barcodes = response.barcodes
self._barcodes = [ProductBarcode(data) for data in response.barcodes]

if response.product:
self._init_from_ProductData(response.product)
Expand Down
6 changes: 3 additions & 3 deletions pygrocy/grocy_api_client.py
Expand Up @@ -365,7 +365,7 @@ def missing_products(self) -> List[MissingProductResponse]:
return self._missing_products


class ProductBarcode(object):
class ProductBarcodeData(object):
def __init__(self, parsed_json):
self._barcode = parsed_json.get("barcode")

Expand Down Expand Up @@ -398,7 +398,7 @@ def __init__(self, parsed_json):
def _parse_barcodes(self, parsed_json):
barcodes_raw = parsed_json.get("product_barcodes", "")
if barcodes_raw is not None:
self._barcodes = [ProductBarcode(barcode) for barcode in barcodes_raw]
self._barcodes = [ProductBarcodeData(barcode) for barcode in barcodes_raw]

def _parse_location(self, parsed_json):
raw_location = parsed_json.get("location")
Expand Down Expand Up @@ -432,7 +432,7 @@ def last_price(self) -> float:
return self._last_price

@property
def barcodes(self) -> List[ProductBarcode]:
def barcodes(self) -> List[ProductBarcodeData]:
return self._barcodes

@property
Expand Down
Expand Up @@ -15,18 +15,19 @@ interactions:
response:
body:
string: !!binary |
H4sIAAAAAAAEA81UTW/bMAz9K4PObWEnS7D5OmDn3YeBYGTaFipLqiwly4r+91GSHTdD9tHbLkHM
jyeS75HPwnnbRhlE8yxUKxpRV+JOGByJ/38aiCbi75Ym6ZULyhrRmKj13ZIHvbfRQU7dcyTKoI4p
t+YPbSWmnOLesGUarHPK9HDlKohPkePARS8H5FcbseWEYpyClY+rpeNXrL+EQrCwRNQPqf5RmWIB
HG003J1I5pY6jDrAgab001lP0OJ5+osbsAvkwTri7v8INEd2nugHd/lv0WHA0xrslAyR6+qUJig8
lPGQwQObArLzRKofAgxoWr2mvnKll/MkjA0gB5KP8zy6qBlZj2QCcP/gSSpHywQcg7Nj1kSmrTwu
UVuvcly9SbzIOEaNgeDXUYPtYIqHBWNBbiOXfnaLMp6i4pKkNVMcaSWpsDeoloBVkzkFeyR/VHSa
h+ntCaQnfrqFoEZmEkfHvk21qe6rD/f1/l21b95vm91evKwyPaCXlmUsmq/fWJjIAliUllS/ZFdJ
w9kbJ2JH6b4UcpHSjmOK6Yg6ppb29cNmtZbArJeEkRXzGgKw7z31qQX27jJPV/6kNG7vKqzQuSj4
KaIJKpwhGrV2clnixNC8w1+QN+fmBr9lkgUOnI4eNRedUCeGLYakpJFHm6bFM78uLnf2n1RWePdK
Zh3WD9t0k/DYs1pn26YQaTVrJS3CtTnn375hIkEt9NwOKWIy9D1AWoeWBcCjLNL7eF+kN1/My7wS
6szkZ6/a/jfX+G1cqgnyiSKf1cmUIS8Z9gTTQLoDrbrlMO5q1rqzSoNP2+7IS74QoqnuBKOsCl13
uBIvPwHQ5/ECVgYAAA==
H4sIAAAAAAAEA8WVTW/bMAyG/0qhc1PY+Sg2XwfsvPswEIpM20JlSZWlZF3R/z5Ksuxk6LLttEtR
kxRF8n3EvDLrTBuEZ80rky1rWF2xe6b5iPT/pwFxQvpucRJOWi+NZo0OSt2Xc9A7Eyyko48UyYWX
p3i2pg9lBI9nsntLlmkw1krdw5UrZ3wOFAc2ODFwurVhOzqQjZM34mm1dHSLcUsoeAMlon6I9Y9S
Zwvw0QRN3bFobrHjQXk44hT/dMYhtPxl+oMbeOfRgbFI3d9MNEd2DvEHdfl30X7g5zXYSuED1dVJ
hZB1yONBzY9k8pycZ5T94GHgulXr0QtXvDlNQhsPYkDxNM+jC4oyqxG1B+ofHAppsUzAUnJyzEwk
2fLlgivjZIqrt1EXEcaguEf4ddRgOpjCseQomdtApb/YQsZzkFSSMHoKI64iZfUG2SIQNUlTMCd0
J4nneZjOnEE4pKtb8HIkJfloybettvWm2m7q3V39sdnXze6Rva2YHrkThjBmzdcZ9D11cdloJn+O
o4TU5/5AMYlA+o5dLzTlQt+nmUXQFSfErJOCOs4jvF34blMf7qpDs9832w90nnSLs+JHwd6+lXTz
04jPtLRbxbLSZWFCcuS78uSWamMb2XTiKiQNDg/1as2BCfCYIyF+mQJ43zvs48zJe0hgXfnj0yA9
rsIyf+XJPQeuvfQvELSkwSyPfBYjdjEvnS+cnvq7K+f2BC+lj9rGdGBVcFxR0THrRNZsiOiPxEKc
FkFyXVzqbNmH/7eyS4zY7uEQNeOnvpBFpgSAUYT2wluxpsM3GC3avB+SSdL43UN8vC2pv3C321Rx
2Zclvgwrkj/L+NnJtv/Nb8e/CSknSAsVXUKT9OK0EniPMA2oOlCyK2v8UBPo1kgFLu4mi07QPmNN
dc8oy4rnunEq9vYTr/Y7BgQHAAA=
headers:
Access-Control-Allow-Headers:
- '*'
Expand All @@ -41,59 +42,7 @@ interactions:
Content-Type:
- application/json
Date:
- Fri, 12 Feb 2021 05:44:44 GMT
Server:
- nginx/1.18.0
Transfer-Encoding:
- chunked
X-Powered-By:
- PHP/7.4.14
status:
code: 200
message: OK
- request:
body: null
headers:
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.25.1
accept:
- application/json
method: GET
uri: https://localhost/api/stock/products/10
response:
body:
string: !!binary |
H4sIAAAAAAAEA81UTW/bMAz9K4PObWEnS7D5OmDn3YeBYGTaFipLqiwly4r+91GSHTdD9tHbLkHM
jyeS75HPwnnbRhlE8yxUKxpRV+JOGByJ/38aiCbi75Ym6ZULyhrRmKj13ZIHvbfRQU7dcyTKoI4p
t+YPbSWmnOLesGUarHPK9HDlKohPkePARS8H5FcbseWEYpyClY+rpeNXrL+EQrCwRNQPqf5RmWIB
HG003J1I5pY6jDrAgab001lP0OJ5+osbsAvkwTri7v8INEd2nugHd/lv0WHA0xrslAyR6+qUJig8
lPGQwQObArLzRKofAgxoWr2mvnKll/MkjA0gB5KP8zy6qBlZj2QCcP/gSSpHywQcg7Nj1kSmrTwu
UVuvcly9SbzIOEaNgeDXUYPtYIqHBWNBbiOXfnaLMp6i4pKkNVMcaSWpsDeoloBVkzkFeyR/VHSa
h+ntCaQnfrqFoEZmEkfHvk21qe6rD/f1/l21b95vm91evKwyPaCXlmUsmq/fWJjIAliUllS/ZFdJ
w9kbJ2JH6b4UcpHSjmOK6Yg6ppb29cNmtZbArJeEkRXzGgKw7z31qQX27jJPV/6kNG7vKqzQuSj4
KaIJKpwhGrV2clnixNC8w1+QN+fmBr9lkgUOnI4eNRedUCeGLYakpJFHm6bFM78uLnf2n1RWePdK
Zh3WD9t0k/DYs1pn26YQaTVrJS3CtTnn375hIkEt9NwOKWIy9D1AWoeWBcCjLNL7eF+kN1/My7wS
6szkZ6/a/jfX+G1cqgnyiSKf1cmUIS8Z9gTTQLoDrbrlMO5q1rqzSoNP2+7IS74QoqnuBKOsCl13
uBIvPwHQ5/ECVgYAAA==
headers:
Access-Control-Allow-Headers:
- '*'
Access-Control-Allow-Methods:
- GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:
- '*'
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json
Date:
- Fri, 12 Feb 2021 05:44:44 GMT
- Mon, 15 Mar 2021 05:45:15 GMT
Server:
- nginx/1.18.0
Transfer-Encoding:
Expand Down
15 changes: 15 additions & 0 deletions test/test_misc.py
@@ -0,0 +1,15 @@
from pygrocy.data_models.product import ProductBarcode
from pygrocy.grocy_api_client import ProductBarcodeData


class TestMisc:
def test_158_productbarcode_deserialization(self):
parsed_data = {"barcode": "123"}
data = ProductBarcodeData(parsed_data)

barcode = ProductBarcode(data)
result = barcode.toJson()

assert result is not None
assert "barcode" in result
assert "123" in result
8 changes: 6 additions & 2 deletions test/test_product.py
@@ -1,6 +1,6 @@
import pytest

from pygrocy.data_models.product import Product
from pygrocy.data_models.product import Product, ProductBarcode
from pygrocy.errors.grocy_error import GrocyError


Expand All @@ -22,9 +22,13 @@ def test_product_get_details_valid(self, grocy):
assert isinstance(product, Product)
assert product.name == "Cheese"
assert product.available_amount == 5
assert len(product.barcodes) == 0
assert product.product_group_id == 6

assert len(product.product_barcodes) == 1
barcode = product.product_barcodes[0]
assert isinstance(barcode, ProductBarcode)
assert barcode.barcode == "12345"

@pytest.mark.vcr
def test_product_no_barcodes(self, grocy):
stock = grocy.stock()
Expand Down

0 comments on commit 7afc1b3

Please sign in to comment.