Comments (10)
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.
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.
@bodgit Does that answer your question?
from furl.
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.
Is it your code or SQLAlchemy-Utils' code that uses furl objects as dictionary keys?
from furl.
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.
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.
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.
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.
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)
- furl doesn't type-hint itself as Text HOT 3
- url parsing still accepts semicolon as separator HOT 5
- Add typing support HOT 6
- Hi, if the URL is like '127.0.0.1:8080/a/b', the result is '8080/a/b', which seems incorrect HOT 2
- How handle javascript:void(0) HOT 2
- Feature: Addition of `is_domain` flag
- Maximum recursion depth exceeded error for url with large list HOT 3
- Adding README to PyPi HOT 2
- '127.0.0.1:8329' parsed wrong in Python 3.9+ HOT 3
- Add SECURITY.md HOT 3
- Feature request: Convert to unescaped string HOT 2
- .join() and .path.normalize() incorrectly interpret base paths ending /. or /..
- furl.path object is NOT of type: pathlib.Path HOT 1
- Feature requests: get url relative to another url
- Setting multiple query params for the same key and resultant url format
- Seems to be a bug when paring multiple '@'s ?
- Use the `ipaddress` module to detect valid IPV6 HOT 1
- a method to set an individual query parameter without removing the rest or keeping the original value
- Removes "git@" from git remote URL HOT 1
- URL fragment percent-encoding
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from furl.