Python Forum

Full Version: Wrong type error
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I'm trying to use a library writen by someone else. Here is a simplified version of my source code:

import growattServer
import datetime
import time
from datetime import date
import getpass
import json
import sys, getopt
import shutil
from enum import IntEnum

# set up variables
user_name = "rowan.bradley"	# Server username
user_pass = "xxxxx" # Server password
outfolder = "/growatt"
outPrefix = "growatt-"
outSuffix = ".json"

api = growattServer.GrowattApi(False, "hue73jhns83je93jed723uj2")
login_response = api.login(user_name, user_pass)
plantId = login_response['data'][0]['plantId']
plant_info = api.plant_info(plantId)
today = date.today()
plant_detail = api.plant_detail(plantId, 1, ime.time()) 
print("plant_detail = ", plant_detail)
When I run this (in WIndows 10) I get
Error:
D:\XPS_8700 Extended Files\Users\RowanB\Documents\Inetpub\www.sylvesterbradley.org\public_html>python growatt2.py Traceback (most recent call last): File "D:\XPS_8700 Extended Files\Users\RowanB\Documents\Inetpub\www.sylvesterbradley.org\public_html\growatt2.py", line 22, in <module> plant_detail = api.plant_detail(plantId, 1, time.time()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\python311\Lib\site-packages\growattServer\__init__.py", line 158, in plant_detail date_str = self.__get_date_string(timespan, date) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\python311\Lib\site-packages\growattServer\__init__.py", line 49, in __get_date_string assert timespan in Timespan ^^^^^^^^^^^^^^^^^^^^ File "c:\python311\Lib\enum.py", line 739, in __contains__ raise TypeError( TypeError: unsupported operand type(s) for 'in': 'int' and 'EnumType' D:\XPS_8700 Extended Files\Users\RowanB\Documents\Inetpub\www.sylvesterbradley.org\public_html>
I suppose that this possibly means that the 3rd parameter for the function api.plant_detail is the wrong type. How do I find out what type is expected? What might it be (so I can try all possibilities)?

Thank you - Rowan
Start by going to the homepage;

https://github.com/indykoning/PyPi_GrowattServer

On that page they have an example using plant_detail:
api.plant_detail(plant_id, timespan<1=day, 2=month>, date)
Problem here is there is no type annotation telling us what timespan or date are supposed to be. Looks like timespan can be 1 or 2.

Next I look though the examples. Unfortunately, there are none that use plant_detail.

Finally, I look at the source code. I see that Timespan is an enumerated type defined by the module,
class Timespan(IntEnum):
    hour = 0
    day = 1
    month = 2

    def __get_date_string(self, timespan=None, date=None):
        if timespan is not None:
         assert timespan in Timespan

        if date is None:
          date = datetime.datetime.now()

        date_str=""
        if timespan == Timespan.month:
            date_str = date.strftime('%Y-%m')
        else:
            date_str = date.strftime('%Y-%m-%d')

        return date_str

    def plant_detail(self, plant_id, timespan, date=None):
        """
        Get plant details for specified timespan.
        """
        date_str = self.__get_date_string(timespan, date)

        response = self.session.get(self.get_url('PlantDetailAPI.do'), params={
            'plantId': plant_id,
            'type': timespan.value,
            'date': date_str
        })
        data = json.loads(response.content.decode('utf-8'))
        return data['back']
From this you can see that date is a datetime object and timespan is a Timespan object. Using assert is poor coding in my opinion, but the test here is to verify that the timespan argument is a Timespan object. You have to pass something like Timespan.day or Timespan.month. You cannot pass 1 or 2.

What's funny is you probably won't get this error if you run your program from the command line. When Python compiles your program into bytecode it will likely remove the assertion. This does not happen when you run your program from an IDE like VSCode, pycharm, spyder...
(Aug-04-2023, 08:42 PM)deanhystad Wrote: [ -> ]What's funny is you probably won't get this error if you run your program from the command line. When Python compiles your program into bytecode it will likely remove the assertion. This does not happen when you run your program from an IDE like VSCode, pycharm, spyder...
Has to pass in -O for it to remove the assert statements.
Agree this is really bad code in an API,i would say it's an plain error as this not documented.

rowan_bradley as i have your password i can test this out.
import time
from datetime import date
import getpass
import json
import sys, getopt
import shutil
from enum import IntEnum

class Timespan(IntEnum):
    hour = 0
    day = 1
    month = 2

# set up variables
user_name = "rowan.bradley" # Server username
user_pass = "xxxxx" # Server password
outfolder = "/growatt"
outPrefix = "growatt-"
outSuffix = ".json"

api = growattServer.GrowattApi(False, "hue73jhns83je93jed723uj2")
login_response = api.login(user_name, user_pass)
plantId = login_response['data'][0]['plantId']
plant_info = api.plant_info(plantId)
today = date.today()
plant_detail = api.plant_detail(plantId, timespan=Timespan.day, date=today)
print("plant_detail = ", plant_detail)
Output:
G:\div_code\egg λ python -O grow.py plant_detail = {'plantData': {'plantMoneyText': '0.0 ', 'plantId': '2016929', 'currentEnergy': '7.8 kWh', 'plantName': 'SYLVESTER-BRADLEY CB8'}, 'data': {}, 'success': True}
Running this normal as most will do without using -O,will get the error.
Output:
G:\div_code\egg λ python grow.py Traceback (most recent call last): File "G:\div_code\egg\grow.py", line 28, in <module> plant_detail = api.plant_detail(plantId, timespan=Timespan.day, date=today) File "C:\Python310\lib\site-packages\growattServer\__init__.py", line 158, in plant_detail date_str = self.__get_date_string(timespan, date) File "C:\Python310\lib\site-packages\growattServer\__init__.py", line 49, in __get_date_string assert timespan in Timespan AssertionError
(Aug-04-2023, 08:42 PM)deanhystad Wrote: [ -> ]Start by going to the homepage;

https://github.com/indykoning/PyPi_GrowattServer

On that page they have an example using plant_detail:
api.plant_detail(plant_id, timespan<1=day, 2=month>, date)
Problem here is there is no type annotation telling us what timespan or date are supposed to be. Looks like timespan can be 1 or 2.

Next I look though the examples. Unfortunately, there are none that use plant_detail.

Finally, I look at the source code. I see that Timespan is an enumerated type defined by the module,
class Timespan(IntEnum):
    hour = 0
    day = 1
    month = 2

    def __get_date_string(self, timespan=None, date=None):
        if timespan is not None:
         assert timespan in Timespan

        if date is None:
          date = datetime.datetime.now()

        date_str=""
        if timespan == Timespan.month:
            date_str = date.strftime('%Y-%m')
        else:
            date_str = date.strftime('%Y-%m-%d')

        return date_str

    def plant_detail(self, plant_id, timespan, date=None):
        """
        Get plant details for specified timespan.
        """
        date_str = self.__get_date_string(timespan, date)

        response = self.session.get(self.get_url('PlantDetailAPI.do'), params={
            'plantId': plant_id,
            'type': timespan.value,
            'date': date_str
        })
        data = json.loads(response.content.decode('utf-8'))
        return data['back']
From this you can see that date is a datetime object and timespan is a Timespan object. Using assert is poor coding in my opinion, but the test here is to verify that the timespan argument is a Timespan object. You have to pass something like Timespan.day or Timespan.month. You cannot pass 1 or 2.

What's funny is you probably won't get this error if you run your program from the command line. When Python compiles your program into bytecode it will likely remove the assertion. This does not happen when you run your program from an IDE like VSCode, pycharm, spyder...
Thank you very much. Using the info you have provided I have eventually got this to work. Several questions/comments arise:
  1. It seems really odd that it won't accept "1" or "2"
  2. Given that it won't accept these, the function description api.plant_detail(plant_id, timespan<1=day, 2=month>, date) seems totally unhelpful and positively misleading.
  3. I had to put a definition of Timespan into my main program to get it to work. Else I get NameError: name 'Timespan' is not defined
But never mind, this hurdle has been overcome, so on to the next challenge!

Thank you - Rowan
Import Timespan from the module.
from growattServer import GrowattApi, Timespan
(Aug-06-2023, 02:13 AM)deanhystad Wrote: [ -> ]Import Timespan from the module.
from growattServer import GrowattApi, Timespan

That seems to work, but now I'm stuck on another problem, which I think is a problem with the API, not my python. I have asked Indy for help on the latest error.

Thank you - Rowan