618604832ee3faa7bc7cf4809dc3f03794be62bb
1 from floof
.model
import Art
, ArtUser
, ArtUserType
, Tag
, TagText
, User
3 from dbhelpers
import find_or_create
5 def parse(search_string
):
6 """Parses a search query, and returns a query object on Art.
10 - User relations: by:kalu, of:eevee, for:ootachi
13 - Negative versions of anything above: -by:eevee, -dongs
16 # XXX doesn't do negative querying yet.
17 # XXX could use some sane limits.
19 # We'll be building this as we go.
22 terms
= search_string
.split()
25 # This is a special tag; at the moment, by/for/of to indicate
27 prefix
, tag
= tag
.split(':', 1)
29 # XXX what to do if this fails? abort? return empty query?
30 target_user
= User
.get_by(name
=tag
)
39 # Bogus tag. Not sure what to do here, so for the moment,
43 # Inner join to the ArtUser table
44 q
= q
.join(ArtUser
, aliased
=True) \
45 .filter(ArtUser
.user
== target_user
) \
46 .filter(ArtUser
.type == rel
)
50 q
= q
.join(Tag
, TagText
, aliased
=True) \
51 .filter(TagText
.text
== tag
)
55 def add_tags(art
, tag_string
, user
):
56 """Takes a string that looks like a tag query, and effectively modifies the
57 art's tags to match it.
60 # XXX what to do with invalid tags? just return them and let caller fix?
62 for tag_text
in tag_string
.split():
63 original_tag_text
= tag_text
64 tag_text
= tag_text
.lower()
66 # Adding or removing a tag?
67 if tag_text
[0] == '-':
69 tag_text
= tag_text
[1:]
71 # Allow "+foo" to mean "add foo"
72 if tag_text
[0] == '+':
73 tag_text
= tag_text
[1:]
76 # Check for special namespaces
79 prefix
, tag_text
= tag_text
.split(':', 1)
80 if prefix
not in ['by', 'for', 'of']:
81 # This is bogus. Skip it.
82 bad_tags
.append(original_tag_text
)
86 # XXX this needs supporting. silently ignore for now
89 # Must be 3-50 alphanumeric characters
90 if not re
.match('^[a-z0-9]{3,50}$', tag_text
):
91 bad_tags
.append(original_tag_text
)
96 target_user
= User
.get_by(name
=tag_text
)
98 # Special tag; at the moment, just a relationship
101 elif prefix
== 'for':
102 rel
= ArtUserType
.FOR
106 user_assoc_data
= dict(art
=art
, user
=target_user
, type=rel
)
108 find_or_create(ArtUser
, **user_assoc_data
)
111 # XXX this will die for nonassociations
112 user_assoc
= ArtUser
.get_by(art
=art
, **user_assoc_data
)
118 tag
= find_or_create(TagText
, text
=tag_text
)
119 find_or_create(Tag
, art
=art
, tagger
=user
, tagtext
=tag
)
122 tag
= TagText
.get_by(text
=tag_text
)
125 tag_assoc
= Tag
.get_by(art
=art
, tagger
=user
, tagtext
=tag
)
128 elixir
.session
.commit()