Git Product home page Git Product logo

Comments (10)

gruns avatar gruns commented on July 26, 2024

Odd. This behavior differs between Python 2

>>> sys.version_info[:2]
(2, 7)
>>> from furl import furl
>>> hash(furl())
1520225

and Python 3.

>>> sys.version_info[:2]
(3, 5)
>>> from furl import furl
>>> hash(furl())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'furl'

I'll look into this.

from furl.

gruns avatar gruns commented on July 26, 2024

On reflection, furl objects should not be used as dictionary keys. They're mutable.

From Python 3's datamodel documentation

If a class defines mutable objects and implements an __eq__() method, it should
not implement __hash__(), since the implementation of hashable collections
requires that a key’s hash value is immutable (if the object’s hash value
changes, it will be in the wrong hash bucket).

Example of potential confusion due to mutability.

>>> f = furl('http://google.com/')
>>> d = {f: f.host}
>>> f.url, d[f] 
('http://google.com/', 'google.com')
>>> f.set(host='yahoo.com')
>>> f.url, d[f]
('http://yahoo.com/', 'google.com')

from furl.

gruns avatar gruns commented on July 26, 2024

@bodgit Does that answer your question?

from furl.

bodgit avatar bodgit commented on July 26, 2024

Your explanation and example makes complete sense, however I guess my problem still remains that the column type doesn't work without my monkeypatch.

I'm not sure why there's even a requirement to use the furl object as a hash key, I think it comes from SQLAlchemy direct rather than the code implementing this URLType column type, specifically this line https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/identity.py#L149 triggers the exception.

The other option I've seen used elsewhere (possibly incorrectly) is to use the return value of id() which would mean it's independent of the value of the object but then I guess two furl objects containing the same URL would have different id() values when you would expect them to hash to the same value.

I guess it's a balancing between what's correct and what just makes the error go away 😉

from furl.

gruns avatar gruns commented on July 26, 2024

Is it your code or SQLAlchemy-Utils' code that uses furl objects as dictionary keys?

from furl.

bodgit avatar bodgit commented on July 26, 2024

Neither, I think it's from the base SQLAlchemy library itself, see the line I linked above that shows where it first tries to hash the value.

from furl.

gruns avatar gruns commented on July 26, 2024

What I mean is, whose code stores furl objects as dictionary keys? That is, in
whose code is SQLAlchemy.orm.identity.WeakInstanceDict.__setitem__() (or
similar) called with a furl object?

If furl objects are stored as dictionary keys in your code, a simple solution is
to wrap the dictionary with a thin shim that serializes and deserializes furl
objects to their URL strings on insertion and back on retrieval.

If furl objects are stored as dictionary keys in SQLAlchemy-Utils' code, I'll
contact them and let them know furl objects are mutable and shouldn't be
dictionary keys.

from furl.

bodgit avatar bodgit commented on July 26, 2024

I think it's SQLAlchemy itself; neither my code nor what I can see in the SQLAlchemy-Utils does anything with dictionaries.

I think it must be doing it for some sort of de-duplication or maybe testing for modification.

I did inquire on their IRC channel but didn't really get anything useful back, I suspect their mailling list is the next step.

from furl.

bodgit avatar bodgit commented on July 26, 2024

I've since found I only get this error when I try to use the URLType as (part of) a primary key, which is what I was trying to do initially.

However whilst this worked with SQLite as a storage backend, MySQL for example complains that the underlying column type (TEXT) cannot be indexed without specifying how many characters to use so I've reworked my code so that I don't use the URL directly as a primary key and then the error disappeared and no monkeypatching is required.

from furl.

gruns avatar gruns commented on July 26, 2024

Great to hear you found a solution. Closing this issue.

Thank you for bringing this to my attention, Matt. Don't hesitate to let me know
if there's anything else I can help with.

from furl.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.