d2adafc4726685729da5f74bdb24bbd6fd110f26
1 from floof
.model
import Art
, ArtUser
, ArtUserType
, Tag
, TagText
, User
3 from dbhelpers
import find_or_create
8 def parse(search_string
):
9 """Parses a search query, and returns a query object on Art.
13 - User relations: by:kalu, of:eevee, for:ootachi
16 - Negative versions of anything above: -by:eevee, -dongs
19 # XXX doesn't do negative querying yet.
20 # XXX could use some sane limits.
22 # We'll be building this as we go.
25 terms
= search_string
.split()
28 # This is a special tag; at the moment, by/for/of to indicate
30 prefix
, tag
= tag
.split(':', 1)
34 # XXX what to do if this fails? abort? return empty query?
35 target_user
= User
.get_by(name
=tag
)
44 # Bogus tag. Not sure what to do here, so for the moment,
48 # Inner join to the ArtUser table
49 q
= q
.join(ArtUser
, aliased
=True) \
50 .filter(ArtUser
.user
== target_user
) \
51 .filter(ArtUser
.type == rel
)
55 q
= q
.join(Tag
, TagText
, aliased
=True) \
56 .filter(TagText
.text
== tag
)
60 def add_tags(art
, tag_string
, user
):
61 """Takes a string that looks like a tag query, and effectively modifies the
62 art's tags to match it.
65 # XXX what to do with invalid tags? just return them and let caller fix?
67 for tag_text
in tag_string
.split():
68 original_tag_text
= tag_text
69 tag_text
= tag_text
.lower()
71 # Adding or removing a tag?
72 if tag_text
[0] == '-':
74 tag_text
= tag_text
[1:]
76 # Allow "+foo" to mean "add foo"
77 if tag_text
[0] == '+':
78 tag_text
= tag_text
[1:]
81 # Check for special namespaces
84 prefix
, tag_text
= tag_text
.split(':', 1)
85 if prefix
not in ['by', 'for', 'of']:
86 # This is bogus. Skip it.
87 bad_tags
.append(original_tag_text
)
91 # XXX this needs supporting. silently ignore for now
94 # Must be 3-50 alphanumeric characters
95 if not re
.match('^[a-z0-9]{3,50}$', tag_text
):
96 bad_tags
.append(original_tag_text
)
101 target_user
= User
.get_by(name
=tag_text
)
103 # Special tag; at the moment, just a relationship
106 elif prefix
== 'for':
107 rel
= ArtUserType
.FOR
111 user_assoc_data
= dict(art
=art
, user
=target_user
, type=rel
)
113 find_or_create(ArtUser
, **user_assoc_data
)
116 # XXX this will die for nonassociations
117 user_assoc
= ArtUser
.get_by(art
=art
, **user_assoc_data
)
123 tag
= find_or_create(TagText
, text
=tag_text
)
124 find_or_create(Tag
, art
=art
, tagger
=user
, tagtext
=tag
)
127 tag
= TagText
.get_by(text
=tag_text
)
130 tag_assoc
= Tag
.get_by(art
=art
, tagger
=user
, tagtext
=tag
)
133 elixir
.session
.commit()