gtalarico / pyairtable

Python Api Client for Airtable
https://pyairtable.readthedocs.io
MIT License
786 stars 139 forks source link

Field values of ORM instances being overwritten by calls to `from_id` #184

Closed larsakerson closed 1 year ago

larsakerson commented 2 years ago

Cross-posting this issue here in case it has something to do with this package.

The gist is that, under certain circumstances, when I create a list of Model instances via the from_id method, the field values for previously-created instances are all overwritten with each call to from_id. The id values of the instances are not affected. I'm not sure, but I wonder if _fields is being declared as both a class variable and an instance variable and causing this issue.

Am I missing something else? Is this an issue with pyairtable, an unexpected interaction with flask-login, or just down to my implementation?

gtalarico commented 2 years ago

@aleafa can you provide a small reproducible example where this happens? There might be something else going. _fields is defined only to define type and a default class value but internally we use self._fields which should set only the instance value. To set class value you would need to use ClassName_fields

Here is a test where I do sequential from_id and result seems ok.

def test_multiple():
    class Address(Model):
        street = f.TextField("Street")

        class Meta:
            base_id = "address_base_id"
            table_name = "Address"
            api_key = "fake"

    record = {"id": "recFake", "createdTime": "", "fields": {"Street": "A"}}
    record_2 = {"id": "recFake2", "createdTime": "", "fields": {"Street": "B"}}
    address = Address.from_id(record["id"], fetch=False)
    address_2 = Address.from_id(record_2["id"], fetch=False)

    with Mocker() as mock:
        url = address.get_table().get_record_url(address.id)
        mock.get(url, status_code=200, json=record)
        address.fetch()
    with Mocker() as mock:
        url = address_2.get_table().get_record_url(address_2.id)
        mock.get(url, status_code=200, json=record_2)
        address_2.fetch()

    assert address.street == "A"
    assert address_2.street == "B"

Happy to look a bit deeper if you can provide a MRE

mesozoic commented 1 year ago

Closing this since we can't reproduce it. If you have a reproducible example, please open a new issue.