Search for movies by title.

Args:
    query: CGI escpaed string.
    page: (optional) Minimum value of 1. Expected value is an integer.
    language: (optional) ISO 639-1 code.
    include_adult: (optional) Toggle the inclusion of adult titles.
                   Expected value is True or False.
    year: (optional) Filter the results release dates to matches that
          include this value.
    primary_release_year: (optional) Filter the results so that only
                          the primary release dates have this value.
    search_type: (optional) By default, the search type is 'phrase'.
                 This is almost guaranteed the option you will want.
                 It's a great all purpose search type and by far the
                 most tuned for every day querying. For those wanting
                 more of an "autocomplete" type search, set this
                 option to 'ngram'.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_path('<STR_LIT>')<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Search for collections by name.

Args:
    query: CGI escpaed string.
    page: (optional) Minimum value of 1. Expected value is an integer.
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Search for TV shows by title.

Args:
    query: CGI escpaed string.
    page: (optional) Minimum value of 1. Expected value is an integer.
    language: (optional) ISO 639-1 code.
    first_air_date_year: (optional) Filter the results to only match
                         shows that have a air date with with value.
    search_type: (optional) By default, the search type is 'phrase'.
                 This is almost guaranteed the option you will want.
                 It's a great all purpose search type and by far the
                 most tuned for every day querying. For those wanting
                 more of an "autocomplete" type search, set this
                 option to 'ngram'.

Returns:
    A dict respresentation of the JSON returned from the API.


Search for people by name.

Args:
    query: CGI escpaed string.
    page: (optional) Minimum value of 1. Expected value is an integer.
    include_adult: (optional) Toggle the inclusion of adult titles.
                   Expected value is True or False.
    search_type: (optional) By default, the search type is 'phrase'.
                 This is almost guaranteed the option you will want.
                 It's a great all purpose search type and by far the
                 most tuned for every day querying. For those wanting
                 more of an "autocomplete" type search, set this
                 option to 'ngram'.

Returns:
    A dict respresentation of the JSON returned from the API.


Search for companies by name.

Args:
    query: CGI escpaed string.
    page: (optional) Minimum value of 1. Expected value is an integer.

Returns:
    A dict respresentation of the JSON returned from the API.


Search for keywords by name.

Args:
    query: CGI escpaed string.
    page: (optional) Minimum value of 1. Expected value is an integer.

Returns:
    A dict respresentation of the JSON returned from the API.


Search the movie, tv show and person collections with a single query.

Args:
    query: CGI escpaed string.
    page: (optional) Minimum value of 1. Expected value is an integer.
    language: (optional) ISO 639-1 code.
    include_adult: (optional) Toggle the inclusion of adult titles.
                   Expected value is True or False.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT:info>')<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get the basic movie information for a specific movie id.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT>')<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get the alternative titles for a specific movie id.

Args:
    country: (optional) ISO 3166-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the cast and crew information for a specific movie id.

Args:
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the external ids for a specific movie id.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the images (posters and backdrops) for a specific movie id.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.
    include_image_language: (optional) Comma separated, a valid
                            ISO 69-1.

Returns:
    A dict representation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT>')<EOL>response = self._GET(path)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get the plot keywords for a specific movie id.

Returns:
    A dict representation of the JSON returned from the API.


Get a list of recommended movies for a movie.

Args:
    language: (optional) ISO 639-1 code.
    page: (optional) Minimum value of 1.  Expected value is an integer.

Returns:
    A dict representation of the JSON returned from the API.


Get the release dates and certification for a specific movie id.

Args:
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the release date and certification information by country for a
specific movie id.

Args:
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the videos (trailers, teasers, clips, etc...) for a
specific movie id.

Args:
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the translations for a specific movie id.

Args:
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the similar movies for a specific movie id.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the reviews for a particular movie id.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the lists that the movie belongs to.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the changes for a specific movie id.

Changes are grouped by key, and ordered by date in descending order.
By default, only the last 24 hours of changes are returned. The
maximum number of days that can be returned in a single request is 14.
The language is present on fields that are translatable.

Args:
    start_date: (optional) Expected format is 'YYYY-MM-DD'.
    end_date: (optional) Expected format is 'YYYY-MM-DD'.

Returns:
    A dict representation of the JSON returned from the API.


Get the list of upcoming movies. This list refreshes every day.
The maximum number of items this list will include is 100.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.

Returns:
    A dict representation of the JSON returned from the API.


Get the list of movies playing in theatres. This list refreshes
every day. The maximum number of items this list will include is 100.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.

Returns:
    A dict representation of the JSON returned from the API.


Get the list of popular movies on The Movie Database. This list
refreshes every day.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.

Returns:
    A dict representation of the JSON returned from the API.


Get the list of top rated movies. By default, this list will only
include movies that have 10 or more votes. This list refreshes every
day.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.

Returns:
    A dict representation of the JSON returned from the API.


This method lets users get the status of whether or not the movie has
been rated or added to their favourite or watch lists. A valid session
id is required.

Args:
    session_id: see Authentication.

Returns:
    A dict representation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT>')<EOL>payload = {<EOL>'<STR_LIT:value>': kwargs.pop('<STR_LIT:value>', None),<EOL>}<EOL>response = self._POST(path, kwargs, payload)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

This method lets users rate a movie. A valid session id or guest
session id is required.

Args:
    session_id: see Authentication.
    guest_session_id: see Authentication.
    value: Rating value.

Returns:
    A dict representation of the JSON returned from the API.


Get the basic collection information for a specific collection id.
You can get the ID needed for this method by making a /movie/{id}
request and paying attention to the belongs_to_collection hash.

Movie parts are not sorted in any particular order. If you would like
to sort them yourself you can use the provided release_date.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get all of the images for a particular collection by collection id.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.
    include_image_language: (optional) Comma separated, a valid
    ISO 69-1.

Returns:
    A dict representation of the JSON returned from the API.


This method is used to retrieve all of the basic information about a
company.

Args:
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the list of movies associated with a particular company.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any movie method.

Returns:
    A dict representation of the JSON returned from the API.


Get the basic information for a specific keyword id.

Returns:
    A dict representation of the JSON returned from the API.


Get the list of movies for a particular keyword by id.

Args:
    page: (optional) Minimum value of 1.  Expected value is an integer.
    language: (optional) ISO 639-1 code.

Returns:
    A dict representation of the JSON returned from the API.


Get the full details of a review by ID.

Returns:
    A dict representation of the JSON returned from the API.


Get the general person information for a specific id.

Args:
    append_to_response: (optional) Comma separated, any person method.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the movie credits for a specific person id.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any person method.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the TV credits for a specific person id.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any person method.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the combined (movie and TV) credits for a specific person id.

To get the expanded details for each TV record, call the /credit method
with the provided credit_id. This will provide details about which
episode and/or season the credit is for.

Args:
    language: (optional) ISO 639-1 code.
    append_to_response: (optional) Comma separated, any person method.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the external ids for a specific person id.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the images for a specific person id.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the changes for a specific person id.

Changes are grouped by key, and ordered by date in descending order.
By default, only the last 24 hours of changes are returned. The maximum
number of days that can be returned in a single request is 14. The
language is present on fields that are translatable.

Args:
    start_date: (optional) Expected format is 'YYYY-MM-DD'.
    end_date: (optional) Expected format is 'YYYY-MM-DD'.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of popular people on The Movie Database. This list
refreshes every day.

Args:
    page: (optional) Minimum 1, maximum 1000.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_credit_id_path('<STR_LIT:info>')<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get the detailed information about a particular credit record. This is
currently only supported with the new credit model found in TV. These
ids can be found from any TV credit response as well as the tv_credits
and combined_credits methods for people.

The episodes object returns a list of episodes and are generally going
to be guest stars. The season array will return a list of season
numbers.  Season credits are credits that were marked with the
"add to every season" option in the editing interface and are
assumed to be "season regulars".

Args:
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_path('<STR_LIT:list>')<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get a list of valid jobs.

Returns:
    A dict respresentation of the JSON returned from the API.


if isinstance(response, dict):<EOL><INDENT>for key in response.keys():<EOL><INDENT>if not hasattr(self, key) or not callable(getattr(self, key)):<EOL><INDENT>setattr(self, key, response[key])<EOL><DEDENT><DEDENT><DEDENT>

Set attributes to dictionary values.

- e.g.
>>> import tmdbsimple as tmdb
>>> movie = tmdb.Movies(103332)
>>> response = movie.info()
>>> movie.title  # instead of response['title']


path = self._get_path('<STR_LIT:info>')<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get the system wide configuration info.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of supported certifications for movies.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of supported timezones for the API methods that support
them.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_path('<STR_LIT:info>')<EOL>kwargs.update({'<STR_LIT>': self.session_id})<EOL>response = self._GET(path, kwargs)<EOL>self.id = response['<STR_LIT:id>']<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get the basic information for an account.

Call this method first, before calling other Account methods.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT>')<EOL>kwargs.update({'<STR_LIT>': self.session_id})<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get the lists that you have created and marked as a favorite.

Args:
    page: (optional) Minimum 1, maximum 1000.
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of favorite movies for an account.

Args:
    page: (optional) Minimum 1, maximum 1000.
    sort_by: (optional) 'created_at.asc' | 'created_at.desc'
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of favorite TV series for an account.

Args:
    page: (optional) Minimum 1, maximum 1000.
    sort_by: (optional) 'created_at.asc' | 'created_at.desc'
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT>')<EOL>kwargs.update({'<STR_LIT>': self.session_id})<EOL>payload = {<EOL>'<STR_LIT>': kwargs.pop('<STR_LIT>', None), <EOL>'<STR_LIT>': kwargs.pop('<STR_LIT>', None), <EOL>'<STR_LIT>': kwargs.pop('<STR_LIT>', None),<EOL>}<EOL>response = self._POST(path, kwargs, payload)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Add or remove a movie to an accounts favorite list.

Args:
    media_type: 'movie' | 'tv'
    media_id: The id of the media.
    favorite: True (to add) | False (to remove).

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of rated movies (and associated rating) for an account.

Args:
    page: (optional) Minimum 1, maximum 1000.
    sort_by: (optional) 'created_at.asc' | 'created_at.desc'
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of rated TV shows (and associated rating) for an account.

Args:
    page: (optional) Minimum 1, maximum 1000.
    sort_by: (optional) 'created_at.asc' | 'created_at.desc'
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of movies on an account watchlist.

Args:
    page: (optional) Minimum 1, maximum 1000.
    sort_by: (optional) 'created_at.asc' | 'created_at.desc'
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Get the list of TV series on an account watchlist.

Args:
    page: (optional) Minimum 1, maximum 1000.
    sort_by: (optional) 'created_at.asc' | 'created_at.desc'
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Add or remove a movie to an accounts watch list.

Args:
    media_type: 'movie' | 'tv'
    media_id: The id of the media.
    watchlist: True (to add) | False (to remove).

Returns:
    A dict respresentation of the JSON returned from the API.


Generate a valid request token for user based authentication.

A request token is required to ask the user for permission to
access their account.

After obtaining the request_token, either:
(1) Direct your user to:
        https://www.themoviedb.org/authenticate/REQUEST_TOKEN
or:
(2) Call token_validate_with_login() below.

Returns:
    A dict respresentation of the JSON returned from the API.


Authenticate a user with a TMDb username and password.  The user
must have a verified email address and be registered on TMDb.

Args:
    request_token: The token you generated for the user to approve.
    username: The user's username on TMDb.
    password: The user's password on TMDb.

Returns:
    A dict respresentation of the JSON returned from the API.


Generate a session id for user based authentication.

A session id is required in order to use any of the write methods.

Args:
    request_token: The token you generated for the user to approve.
                   The token needs to be approved before being
                   used here.

Returns:
    A dict respresentation of the JSON returned from the API.


Generate a guest session id.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_guest_session_id_path('<STR_LIT>')<EOL>response = self._GET(path, kwargs)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Get a list of rated moview for a specific guest session id.

Args:
    page: (optional) Minimum 1, maximum 1000.
    sort_by: (optional) 'created_at.asc' | 'created_at.desc'
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


Get a list by id.

Returns:
    A dict respresentation of the JSON returned from the API.


Check to see if a movie id is already added to a list.

Args:
    movie_id: The id of the movie.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_path('<STR_LIT>')<EOL>kwargs.update({'<STR_LIT>': self.session_id})<EOL>payload = {<EOL>'<STR_LIT:name>': kwargs.pop('<STR_LIT:name>', None), <EOL>'<STR_LIT:description>': kwargs.pop('<STR_LIT:description>', None),<EOL>}<EOL>if '<STR_LIT>' in kwargs:<EOL><INDENT>payload['<STR_LIT>'] = kwargs['<STR_LIT>']<EOL><DEDENT>response = self._POST(path, kwargs, payload)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Create a new list.

A valid session id is required.

Args:
    name: Name of the list.
    description: Description of the list.
    language: (optional) ISO 639-1 code.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT>')<EOL>kwargs.update({'<STR_LIT>': self.session_id})<EOL>payload = {<EOL>'<STR_LIT>': kwargs.pop('<STR_LIT>', None), <EOL>}<EOL>response = self._POST(path, kwargs, payload)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Add new movies to a list that the user created.

A valid session id is required.

Args:
    media_id: A movie id.

Returns:
    A dict respresentation of the JSON returned from the API.


Delete movies from a list that the user created.

A valid session id is required.

Args:
    media_id: A movie id.

Returns:
    A dict respresentation of the JSON returned from the API.


path = self._get_id_path('<STR_LIT>')<EOL>kwargs.update({'<STR_LIT>': self.session_id})<EOL>payload = {}<EOL>response = self._POST(path, kwargs, payload)<EOL>self._set_attrs_to_values(response)<EOL>return response<EOL>

Clears all of the items within a list. This is an irreversible action
and should be treated with caution.

A valid session id is required.

Args:
    confirm: True (do it) | False (don't do it)

Returns:
    A dict respresentation of the JSON returned from the API.


Get a list of movie ids that have been edited.

Args:
    page: (optional) Minimum 1, maximum 1000.
    start_date: (optional) Expected format is 'YYYY-MM-DD'.
    end_date: (optional) Expected format is 'YYYY-MM-DD'.

Returns:
    A dict respresentation of the JSON returned from the API.


Get a list of people ids that have been edited.

Args:
    page: (optional) Minimum 1, maximum 1000.
    start_date: (optional) Expected format is 'YYYY-MM-DD'.
    end_date: (optional) Expected format is 'YYYY-MM-DD'.

Returns:
    A dict respresentation of the JSON returned from the API.


Get a list of TV show ids that have been edited.

Args:
    page: (optional) Minimum 1, maximum 1000.
    start_date: (optional) Expected format is 'YYYY-MM-DD'.
    end_date: (optional) Expected format is 'YYYY-MM-DD'.

Returns:
    A dict respresentation of the JSON returned from the API.


def send_message(self, message, **kwargs):

from ..libs.gcm import gcm_send_message<EOL>data = kwargs.pop("<STR_LIT>", {})<EOL>if message is not None:<EOL><INDENT>data["<STR_LIT:message>"] = message<EOL><DEDENT>return gcm_send_message(registration_id=self.registration_id,<EOL>data=data, **kwargs)<EOL>

Sends a push notification to this device via GCM


if not isinstance(module_location, (str, unicode)):<EOL><INDENT>raise ValueError("<STR_LIT>""<STR_LIT>""<STR_LIT>" % (module_location, type(module_location)))<EOL><DEDENT>try:<EOL><INDENT>name_split = module_location.split("<STR_LIT:.>")<EOL>class_name = name_split.pop(-<NUM_LIT:1>)<EOL>if not len(name_split):<EOL><INDENT>raise ValueError("<STR_LIT>""<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>module_location = "<STR_LIT:.>".join(name_split)<EOL>module = importlib.import_module(module_location)<EOL>cls = getattr(module, class_name)<EOL>return cls<EOL><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT>

Returns the instance of the given module location.


def apns_send_message(registration_id, alert, **kwargs):

_apns_send(registration_id, alert, **kwargs)<EOL>

Sends an APNS notification to a single registration_id.
This will send the notification as form data.
If sending multiple notifications, it is more efficient to use
apns_send_bulk_message()

Note that if set alert should always be a string. If it is not set,
it won't be included in the notification. You will need to pass None
to this for silent notifications.


def apns_send_bulk_message(registration_ids, alert, **kwargs):

with closing(_apns_create_socket_to_push(**kwargs)) as socket:<EOL><INDENT>for identifier, registration_id in enumerate(registration_ids):<EOL><INDENT>_apns_send(registration_id, alert, identifier=identifier, socket=socket, **kwargs)<EOL><DEDENT>_apns_check_errors(socket)<EOL><DEDENT>

Sends an APNS notification to one or more registration_ids.
The registration_ids argument needs to be a list.

Note that if set alert should always be a string. If it is not set,
it won't be included in the notification. You will need to pass None
to this for silent notifications.


with closing(_apns_create_socket_to_feedback()) as socket:<EOL><INDENT>inactive_ids = []<EOL>for _, registration_id in _apns_receive_feedback(socket):<EOL><INDENT>inactive_ids.append(codecs.encode(registration_id, '<STR_LIT>'))<EOL><DEDENT>return inactive_ids<EOL><DEDENT>

Queries the APNS server for id's that are no longer active since
the last fetch


def gcm_send_message(registration_id, data, encoding='<STR_LIT:utf-8>', **kwargs):

messenger = GCMMessenger(registration_id, data, encoding=encoding, **kwargs)<EOL>return messenger.send_plain()<EOL>

Standalone method to send a single gcm notification


def gcm_send_bulk_message(registration_ids, data, encoding='<STR_LIT:utf-8>', **kwargs):

messenger = GCMMessenger(registration_ids, data, encoding=encoding, **kwargs)<EOL>return messenger.send_bulk()<EOL>

Standalone method to send bulk gcm notifications


values = {"<STR_LIT>": self._registration_id}<EOL>for key, val in self._data.items():<EOL><INDENT>values["<STR_LIT>" % (key)] = val.encode(self.encoding)<EOL><DEDENT>for key, val in self._kwargs.items():<EOL><INDENT>if val and isinstance(val, bool):<EOL><INDENT>val = <NUM_LIT:1><EOL>values[key] = val<EOL><DEDENT><DEDENT>data = urlencode(sorted(values.items())).encode(self.encoding)<EOL>result = self._send(data, "<STR_LIT>")<EOL>if result.startswith("<STR_LIT>"):<EOL><INDENT>if result in ("<STR_LIT>", "<STR_LIT>"):<EOL><INDENT>return result<EOL><DEDENT>raise GCMPushError(result)<EOL><DEDENT>return result<EOL>


items = ids or self._registration_id<EOL>values = {"<STR_LIT>": items}<EOL>if self._data is not None:<EOL><INDENT>values["<STR_LIT:data>"] = self._data<EOL><DEDENT>for key, val in self._kwargs.items():<EOL><INDENT>if val:<EOL><INDENT>values[key] = val<EOL><DEDENT><DEDENT>data = json.dumps(values, separators=("<STR_LIT:U+002C>", "<STR_LIT::>"), sort_keys=True).encode(<EOL>self.encoding)<EOL>result = json.loads(self._send(data, "<STR_LIT:application/json>"))<EOL>if ("<STR_LIT>" in result) and (result["<STR_LIT>"]):<EOL><INDENT>unregistered = []<EOL>throw_error = False<EOL>for index, error in enumerate(result.get("<STR_LIT>", [])):<EOL><INDENT>error = error.get("<STR_LIT:error>", "<STR_LIT>")<EOL>if error in ("<STR_LIT>", "<STR_LIT>"):<EOL><INDENT>unregistered.append(items[index])<EOL><DEDENT>elif error != "<STR_LIT>":<EOL><INDENT>throw_error = True<EOL><DEDENT><DEDENT>self.deactivate_unregistered_devices(unregistered)<EOL>if throw_error:<EOL><INDENT>raise GCMPushError(result)<EOL><DEDENT><DEDENT>return result<EOL>


headers = {<EOL>"<STR_LIT:Content-Type>": content_type,<EOL>"<STR_LIT>": "<STR_LIT>" % (self.api_key),<EOL>"<STR_LIT>": str(len(data))<EOL>}<EOL>request = Request(self.api_url, data, headers)<EOL>return urlopen(request).read().decode(self.encoding)<EOL>

Sends a GCM message with the given content type


for key, value in kwargs.iteritems():<EOL><INDENT>setattr(self, key, value)<EOL><DEDENT>

Allows to initialise the widget with special options.

:param widget_name: By setting the name, you override the get_name
  method and always return that name instead. This allows you to
  register the same widget class several times with different names.


return {'<STR_LIT>': True, }<EOL>

Should return a dictionary of template context variables that are
needed to render this widget.


instance, created =models.DashboardWidgetLastUpdate.objects.get_or_create(<EOL>widget_name=self.get_name())<EOL>return instance<EOL>

Gets or creates the last update object for this widget.


if hasattr(self, '<STR_LIT>'):<EOL><INDENT>return self.widget_name<EOL><DEDENT>return self.__class__.__name__<EOL>

Returns the class name of this widget.

Be careful when overriding this. If ``self.widget_name`` is set, you
should always return that in order to allow to register this widget
class several times with different names.


def get_setting(self, setting_name, default=None):

try:<EOL><INDENT>setting = models.DashboardWidgetSettings.objects.get(<EOL>widget_name=self.get_name(),<EOL>setting_name=setting_name)<EOL><DEDENT>except models.DashboardWidgetSettings.DoesNotExist:<EOL><INDENT>setting = default<EOL><DEDENT>return setting<EOL>

Returns the setting for this widget from the database.

:setting_name: The name of the setting.
:default: Optional default value if the setting cannot be found.


return self.get_name()<EOL>

Returns the title of this widget.

This should be shown on the dashboard.


def save_setting(self, setting_name, value):

setting = self.get_setting(setting_name)<EOL>if setting is None:<EOL><INDENT>setting = models.DashboardWidgetSettings.objects.create(<EOL>widget_name=self.get_name(),<EOL>setting_name=setting_name,<EOL>value=value)<EOL><DEDENT>setting.value = value<EOL>setting.save()<EOL>return setting<EOL>

Saves the setting value into the database.


last_update = self.get_last_update()<EOL>last_update.save()<EOL>


last_update = self.get_last_update()<EOL>time_since = now() - last_update.last_update<EOL>if time_since.seconds < self.update_interval:<EOL><INDENT>return False<EOL><DEDENT>return True<EOL>

Checks if an update is needed.

Checks against ``self.update_interval`` and this widgets
``DashboardWidgetLastUpdate`` instance if an update is overdue.

This should be called by
``DashboardWidgetPool.get_widgets_that_need_update()``, which in turn
should be called by an admin command which should be scheduled every
minute via crontab.


raise NotImplementedError<EOL>

Implement this in your widget in order to update the widget's data.

This is the place where you would call some third party API, retrieve
some data and save it into your widget's model.


def __init__(self, url, token, remote_widget_name, **kwargs):

self.url = url<EOL>self.token = token<EOL>self.remote_widget_name = remote_widget_name<EOL>super(RemoteWidget, self).__init__(**kwargs)<EOL>

Initiates the widget.

:param url: The URL of the remote dashboard api
  (i.e. http://example.com/dashboard/api/widget/)
:param token: The API token you have been given by the admin of the
  remote server in order to obtain this widget.
:remote_widget_name: The widget name as registered on the remote
  server.


return self.get_json_response(self.convert_context_to_json(context))<EOL>

Returns a JSON response containing 'context' as payload


def get_json_response(self, content, **httpresponse_kwargs):

return http.HttpResponse(content,<EOL>content_type='<STR_LIT:application/json>',<EOL>**httpresponse_kwargs)<EOL>


return json.dumps(context)<EOL>

Convert the context dictionary into a JSON object


ctx = super(RenderWidgetMixin, self).get_context_data(**kwargs)<EOL>ctx.update({<EOL>'<STR_LIT>': True,<EOL>'<STR_LIT>': self.widget,<EOL>})<EOL>ctx.update(self.widget.get_context_data())<EOL>return ctx<EOL>

Adds ``is_rendered`` to the context and the widget's context data.

``is_rendered`` signals that the AJAX view has been called and that
we are displaying the full widget now. When ``is_rendered`` is not
found in the widget template it means that we are seeing the first
page load and all widgets still have to get their real data from
this AJAX view.


def permission_required(perm, login_url=None, raise_exception=False):

def check_perms(user):<EOL><INDENT>if not getattr(settings, '<STR_LIT>',<EOL>app_settings.REQUIRE_LOGIN):<EOL><INDENT>return True<EOL><DEDENT>if user.has_perm(perm):<EOL><INDENT>return True<EOL><DEDENT>if raise_exception:  <EOL><INDENT>raise PermissionDenied<EOL><DEDENT>return False<EOL><DEDENT>return user_passes_test(check_perms, login_url=login_url)<EOL>

Re-implementation of the permission_required decorator, honors settings.

If ``DASHBOARD_REQUIRE_LOGIN`` is False, this decorator will always return
``True``, otherwise it will check for the permission as usual.


if self.discovered:<EOL><INDENT>return<EOL><DEDENT>load('<STR_LIT>')<EOL>self.discovered = True<EOL>

Searches for widgets in all INSTALLED_APPS.

This will be called when you call ``get_all_widgets`` for the first
time.


self.discover_widgets()<EOL>return self.widgets<EOL>


result = []<EOL>for widget_name, widget in self.get_widgets().items():<EOL><INDENT>result.append((widget_name, widget, widget.position))<EOL><DEDENT>result.sort(key=lambda x: x[<NUM_LIT:2>])<EOL>return result<EOL>


return self.widgets[widget_name]<EOL>

Returns the widget that matches the given widget name.


result = []<EOL>for widget_name, widget in self.get_widgets().items():<EOL><INDENT>if widget.should_update():<EOL><INDENT>result.append(widget)<EOL><DEDENT><DEDENT>return result<EOL>

Returns all widgets that need an update.

This should be scheduled every minute via crontab.


def register_widget(self, widget_cls, **widget_kwargs):

if not issubclass(widget_cls, DashboardWidgetBase):<EOL><INDENT>raise ImproperlyConfigured(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'.format(widget_cls))<EOL><DEDENT>widget = widget_cls(**widget_kwargs)<EOL>widget_name = widget.get_name()<EOL>if widget_name in self.widgets:<EOL><INDENT>raise WidgetAlreadyRegistered(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'.format(widget_cls, widget_name))<EOL><DEDENT>self.widgets[widget_name] = widget<EOL>

Registers the given widget.

Widgets must inherit ``DashboardWidgetBase`` and you cannot register
the same widget twice.

:widget_cls: A class that inherits ``DashboardWidgetBase``.


if widget_cls.__name__ in self.widgets:<EOL><INDENT>del self.widgets[widget_cls().get_name()]<EOL><DEDENT>


if config:<EOL><INDENT>try:<EOL><INDENT>with open(filename, '<STR_LIT:w>') as fdesc:<EOL><INDENT>fdesc.write(json.dumps(config))<EOL><DEDENT><DEDENT>except IOError as error:<EOL><INDENT>logger.exception(error)<EOL>return False<EOL><DEDENT>return True<EOL><DEDENT>else:<EOL><INDENT>if os.path.isfile(filename):<EOL><INDENT>try:<EOL><INDENT>with open(filename, '<STR_LIT:r>') as fdesc:<EOL><INDENT>return json.loads(fdesc.read())<EOL><DEDENT><DEDENT>except IOError as error:<EOL><INDENT>return False<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return {}<EOL><DEDENT><DEDENT>

Small configuration file management function


url = '<STR_LIT>'<EOL>params = {'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': self.api_key, '<STR_LIT>': '<STR_LIT>'}<EOL>try:<EOL><INDENT>request = requests.get(url, params=params)<EOL><DEDENT>except RequestException:<EOL><INDENT>logger.warn("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>return<EOL><DEDENT>self.authorization_code = request.json()['<STR_LIT:code>']<EOL>self.pin = request.json()['<STR_LIT>']<EOL>logger.error('<STR_LIT>'<EOL>+ self.pin + '<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')<EOL>

Method to request a PIN from ecobee for authorization


url = '<STR_LIT>'<EOL>params = {'<STR_LIT>': '<STR_LIT>', '<STR_LIT:code>': self.authorization_code,<EOL>'<STR_LIT>': self.api_key}<EOL>try:<EOL><INDENT>request = requests.post(url, params=params)<EOL><DEDENT>except RequestException:<EOL><INDENT>logger.warn("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>return<EOL><DEDENT>if request.status_code == requests.codes.ok:<EOL><INDENT>self.access_token = request.json()['<STR_LIT>']<EOL>self.refresh_token = request.json()['<STR_LIT>']<EOL>self.write_tokens_to_file()<EOL>self.pin = None<EOL><DEDENT>else:<EOL><INDENT>logger.warn('<STR_LIT>'<EOL>'<STR_LIT>' + str(request.status_code))<EOL>return<EOL><DEDENT>

Method to request API tokens from ecobee


url = '<STR_LIT>'<EOL>params = {'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': self.refresh_token,<EOL>'<STR_LIT>': self.api_key}<EOL>request = requests.post(url, params=params)<EOL>if request.status_code == requests.codes.ok:<EOL><INDENT>self.access_token = request.json()['<STR_LIT>']<EOL>self.refresh_token = request.json()['<STR_LIT>']<EOL>self.write_tokens_to_file()<EOL>return True<EOL><DEDENT>else:<EOL><INDENT>self.request_pin()<EOL><DEDENT>

Method to refresh API tokens from ecobee


url = '<STR_LIT>'<EOL>header = {'<STR_LIT:Content-Type>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>' + self.access_token}<EOL>params = {'<STR_LIT>': ('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>')}<EOL>try:<EOL><INDENT>request = requests.get(url, headers=header, params=params)<EOL><DEDENT>except RequestException:<EOL><INDENT>logger.warn("<STR_LIT>")<EOL>return None<EOL><DEDENT>if request.status_code == requests.codes.ok:<EOL><INDENT>self.authenticated = True<EOL>self.thermostats = request.json()['<STR_LIT>']<EOL>return self.thermostats<EOL><DEDENT>else:<EOL><INDENT>self.authenticated = False<EOL>logger.info("<STR_LIT>"<EOL>"<STR_LIT>")<EOL>if self.refresh_tokens():<EOL><INDENT>return self.get_thermostats()<EOL><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT><DEDENT>

Set self.thermostats to a json list of thermostats from ecobee


return self.thermostats[index]<EOL>

Return a single thermostat based on index


return self.thermostats[index]['<STR_LIT>']<EOL>


config = dict()<EOL>config['<STR_LIT>'] = self.api_key<EOL>config['<STR_LIT>'] = self.access_token<EOL>config['<STR_LIT>'] = self.refresh_token<EOL>config['<STR_LIT>'] = self.authorization_code<EOL>if self.file_based_config:<EOL><INDENT>config_from_file(self.config_filename, config)<EOL><DEDENT>else:<EOL><INDENT>self.config = config<EOL><DEDENT>


def set_hvac_mode(self, index, hvac_mode):

body = {"<STR_LIT>": {"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": {<EOL>"<STR_LIT>": {<EOL>"<STR_LIT>": hvac_mode<EOL>}<EOL>}}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>

possible hvac modes are auto, auxHeatOnly, cool, heat, off


def set_fan_min_on_time(self, index, fan_min_on_time):

body = {"<STR_LIT>": {"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": {<EOL>"<STR_LIT>": {<EOL>"<STR_LIT>": fan_min_on_time<EOL>}<EOL>}}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>

The minimum time, in minutes, to run the fan each hour. Value from 1 to 60


def set_fan_mode(self, index, fan_mode, cool_temp, heat_temp, hold_type="<STR_LIT>"):

body = {"<STR_LIT>": {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": [{"<STR_LIT:type>": "<STR_LIT>", "<STR_LIT>": {<EOL>"<STR_LIT>": hold_type,<EOL>"<STR_LIT>": int(cool_temp * <NUM_LIT:10>),<EOL>"<STR_LIT>": int(heat_temp * <NUM_LIT:10>),<EOL>"<STR_LIT>": fan_mode<EOL>}}]}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>

Set fan mode. Values: auto, minontime, on


def set_hold_temp(self, index, cool_temp, heat_temp,<EOL>hold_type="<STR_LIT>"):

body = {"<STR_LIT>": {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": [{"<STR_LIT:type>": "<STR_LIT>", "<STR_LIT>": {<EOL>"<STR_LIT>": hold_type,<EOL>"<STR_LIT>": int(cool_temp * <NUM_LIT:10>),<EOL>"<STR_LIT>": int(heat_temp * <NUM_LIT:10>)<EOL>}}]}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>


def set_climate_hold(self, index, climate, hold_type="<STR_LIT>"):

body = {"<STR_LIT>": {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": [{"<STR_LIT:type>": "<STR_LIT>", "<STR_LIT>": {<EOL>"<STR_LIT>": hold_type,<EOL>"<STR_LIT>": climate<EOL>}}]}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>

Set a climate hold - ie away, home, sleep


def delete_vacation(self, index, vacation):

body = {"<STR_LIT>": {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": [{"<STR_LIT:type>": "<STR_LIT>", "<STR_LIT>": {<EOL>"<STR_LIT:name>": vacation<EOL>}}]}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>


def resume_program(self, index, resume_all=False):

body = {"<STR_LIT>": {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": [{"<STR_LIT:type>": "<STR_LIT>", "<STR_LIT>": {<EOL>"<STR_LIT>": resume_all<EOL>}}]}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>


def send_message(self, index, message="<STR_LIT>"):

body = {"<STR_LIT>": {<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": [{"<STR_LIT:type>": "<STR_LIT>", "<STR_LIT>": {<EOL>"<STR_LIT:text>": message[<NUM_LIT:0>:<NUM_LIT>]<EOL>}}]}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>


def set_humidity(self, index, humidity):

body = {"<STR_LIT>": {"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": self.thermostats[index]['<STR_LIT>']},<EOL>"<STR_LIT>": {<EOL>"<STR_LIT>": {<EOL>"<STR_LIT>": int(humidity)<EOL>}<EOL>}}<EOL>log_msg_action = "<STR_LIT>"<EOL>return self.make_request(body, log_msg_action)<EOL>


def set_mic_mode(self, index, mic_enabled):

body = {<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': self.thermostats[index]['<STR_LIT>']},<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': mic_enabled}}}<EOL>log_msg_action = '<STR_LIT>'<EOL>return self.make_request(body, log_msg_action)<EOL>

Enable/disable Alexa mic (only for Ecobee 4)
        Values: True, False


def set_occupancy_modes(self, index, auto_away=None, follow_me=None):

body = {<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': self.thermostats[index]['<STR_LIT>']},<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': auto_away,<EOL>'<STR_LIT>': follow_me}}}<EOL>log_msg_action = '<STR_LIT>'<EOL>return self.make_request(body, log_msg_action)<EOL>

Enable/disable Smart Home/Away and Follow Me modes
        Values: True, False


body = {<EOL>'<STR_LIT>': {<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': self.thermostats[index]['<STR_LIT>']},<EOL>'<STR_LIT>': {<EOL>'<STR_LIT:location>': {<EOL>'<STR_LIT>': dst}}}<EOL>log_msg_action = '<STR_LIT>'<EOL>return self.make_request(body, log_msg_action)<EOL>

Enable/disable daylight savings
        Values: True, False


def get_fake_model(fields=None, model_base=PostgresModel, meta_options={}):

model = define_fake_model(fields, model_base, meta_options)<EOL>class TestProject:<EOL><INDENT>def clone(self, *_args, **_kwargs):<EOL><INDENT>return self<EOL><DEDENT>@property<EOL>def apps(self):<EOL><INDENT>return self<EOL><DEDENT><DEDENT>class TestMigration(migrations.Migration):<EOL><INDENT>operations = [HStoreExtension()]<EOL><DEDENT>with connection.schema_editor() as schema_editor:<EOL><INDENT>migration_executor = MigrationExecutor(schema_editor.connection)<EOL>migration_executor.apply_migration(<EOL>TestProject(), TestMigration('<STR_LIT>', '<STR_LIT>'))<EOL>schema_editor.create_model(model)<EOL><DEDENT>return model<EOL>

Creates a fake model to use during unit tests.


def db_relation_exists(table_name: str) -> bool:

with connection.cursor() as cursor:<EOL><INDENT>cursor.execute(<EOL>"""<STR_LIT>""" % table_name<EOL>)<EOL>return cursor.fetchone()[<NUM_LIT:0>]<EOL><DEDENT>

Gets whether a database relation with the specified name exists.


model = get_fake_model({<EOL>'<STR_LIT:title>': models.CharField(max_length=<NUM_LIT:255>),<EOL>'<STR_LIT>': models.BooleanField(default=False)<EOL>})<EOL>signal_handler = Mock()<EOL>signal.connect(signal_handler, sender=model, weak=False)<EOL>return model, signal_handler<EOL>

Creates a new model and attaches the specified
    signal to a mocked signal handler.

    Returns:
        The created model and the mocked signal handler.


with connection.schema_editor() as schema_editor:<EOL><INDENT>wrapper_for = schema_editor.execute<EOL>with mock.patch.object(BaseDatabaseSchemaEditor, '<STR_LIT>', wraps=wrapper_for) as execute:<EOL><INDENT>filter_results = {}<EOL>yield schema_editor, filter_results<EOL><DEDENT><DEDENT>for filter_text in filters:<EOL><INDENT>filter_results[filter_text] = [<EOL>call for call in execute.mock_calls<EOL>if filter_text in str(call)<EOL>]<EOL><DEDENT>

Gets a schema editor, but filters executed SQL
    statements based on the specified text filters.

    Arguments:
        filters:
            List of strings to filter SQL
            statements on.


def execute_migration(schema_editor, operations, project=None):

project = project or migrations.state.ProjectState.from_apps(apps)<EOL>class Migration(migrations.Migration):<EOL><INDENT>pass<EOL><DEDENT>Migration.operations = operations<EOL>executor = MigrationExecutor(schema_editor.connection)<EOL>executor.apply_migration(<EOL>project, Migration('<STR_LIT>', '<STR_LIT>'))<EOL>

Executes the specified migration operations
    using the specified schema editor.

    Arguments:
        schema_editor:
            The schema editor to use to
            execute the migrations.

        operations:
            The migration operations to execute.

        project:
            The project state to use during the
            migrations.


@contextmanager<EOL>def create_drop_model(field, filters: List[str]):

model = define_fake_model({'<STR_LIT:title>': field})<EOL>with filtered_schema_editor(*filters) as (schema_editor, calls):<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.CreateModel(<EOL>model.__name__,<EOL>fields=[<EOL>('<STR_LIT:title>', field.clone())<EOL>]<EOL>),<EOL>migrations.DeleteModel(<EOL>model.__name__,<EOL>)<EOL>])<EOL><DEDENT>yield calls<EOL>

Creates and drops a model with the specified field.

    Arguments:
        field:
            The field to include on the
            model to create and drop.

        filters:
            List of strings to filter
            SQL statements on.


@contextmanager<EOL>def alter_db_table(field, filters: List[str]):

model = define_fake_model()<EOL>project = migrations.state.ProjectState.from_apps(apps)<EOL>with connection.schema_editor() as schema_editor:<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.CreateModel(<EOL>model.__name__,<EOL>fields=[<EOL>('<STR_LIT:title>', field.clone())<EOL>]<EOL>)<EOL>], project)<EOL><DEDENT>with filtered_schema_editor(*filters) as (schema_editor, calls):<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.AlterModelTable(<EOL>model.__name__,<EOL>'<STR_LIT>'<EOL>)<EOL>], project)<EOL><DEDENT>yield calls<EOL>

Creates a model with the specified field
    and then renames the database table.

    Arguments:
        field:
            The field to include into the
            model.

        filters:
            List of strings to filter
            SQL statements on.


@contextmanager<EOL>def add_field(field, filters: List[str]):

model = define_fake_model()<EOL>project = migrations.state.ProjectState.from_apps(apps)<EOL>with connection.schema_editor() as schema_editor:<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.CreateModel(<EOL>model.__name__,<EOL>fields=[]<EOL>)<EOL>], project)<EOL><DEDENT>with filtered_schema_editor(*filters) as (schema_editor, calls):<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.AddField(<EOL>model.__name__,<EOL>'<STR_LIT:title>',<EOL>field<EOL>)<EOL>], project)<EOL><DEDENT>yield calls<EOL>

Adds the specified field to a model.

    Arguments:
        field:
            The field to add to a model.

        filters:
            List of strings to filter
            SQL statements on.


@contextmanager<EOL>def remove_field(field, filters: List[str]):

model = define_fake_model({'<STR_LIT:title>': field})<EOL>project = migrations.state.ProjectState.from_apps(apps)<EOL>with connection.schema_editor() as schema_editor:<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.CreateModel(<EOL>model.__name__,<EOL>fields=[<EOL>('<STR_LIT:title>', field.clone())<EOL>]<EOL>)<EOL>], project)<EOL><DEDENT>with filtered_schema_editor(*filters) as (schema_editor, calls):<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.RemoveField(<EOL>model.__name__,<EOL>'<STR_LIT:title>'<EOL>)<EOL>], project)<EOL><DEDENT>yield calls<EOL>

Removes the specified field from a model.

    Arguments:
        field:
            The field to remove from a model.

        filters:
            List of strings to filter
            SQL statements on.


@contextmanager<EOL>def alter_field(old_field, new_field, filters: List[str]):

model = define_fake_model({'<STR_LIT:title>': old_field})<EOL>project = migrations.state.ProjectState.from_apps(apps)<EOL>with connection.schema_editor() as schema_editor:<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.CreateModel(<EOL>model.__name__,<EOL>fields=[<EOL>('<STR_LIT:title>', old_field.clone())<EOL>]<EOL>)<EOL>], project)<EOL><DEDENT>with filtered_schema_editor(*filters) as (schema_editor, calls):<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.AlterField(<EOL>model.__name__,<EOL>'<STR_LIT:title>',<EOL>new_field<EOL>)<EOL>], project)<EOL><DEDENT>yield calls<EOL>

Alters a field from one state to the other.

    Arguments:
        old_field:
            The field before altering it.

        new_field:
            The field after altering it.

        filters:
            List of strings to filter
            SQL statements on.


@contextmanager<EOL>def rename_field(field, filters: List[str]):

model = define_fake_model({'<STR_LIT:title>': field})<EOL>project = migrations.state.ProjectState.from_apps(apps)<EOL>with connection.schema_editor() as schema_editor:<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.CreateModel(<EOL>model.__name__,<EOL>fields=[<EOL>('<STR_LIT:title>', field.clone())<EOL>]<EOL>)<EOL>], project)<EOL><DEDENT>with filtered_schema_editor(*filters) as (schema_editor, calls):<EOL><INDENT>execute_migration(schema_editor, [<EOL>migrations.RenameField(<EOL>model.__name__,<EOL>'<STR_LIT:title>',<EOL>'<STR_LIT>'<EOL>)<EOL>], project)<EOL><DEDENT>yield calls<EOL>

Renames a field from one name to the other.

    Arguments:
        field:
            Field to be renamed.

        filters:
            List of strings to filter
            SQL statements on.


import psqlextra.apps<EOL>self.app_label = self._generate_random_name()<EOL>self.app_config = type(self.app_label, (AppConfig,), dict(<EOL>name=self.app_label,<EOL>verbose_name=self.app_label<EOL>))(self.app_label, psqlextra.apps)<EOL>self.app_config.models = {}<EOL>self.apps = Apps()<EOL>self.apps.ready = False<EOL>if django.VERSION >= (<NUM_LIT:2>, <NUM_LIT:0>):<EOL><INDENT>self.apps.loading = False<EOL><DEDENT>self.apps.populate(installed_apps=[self.app_config])<EOL>self.project_state = ProjectState()<EOL>self.migrations = []<EOL>

Creates a new migration simulator with an empty
        project state and no migrations.


new_project_state = ProjectState.from_apps(self.apps)<EOL>autodetector = MigrationAutodetector(<EOL>self.project_state,<EOL>new_project_state<EOL>)<EOL>changes = autodetector._detect_changes()<EOL>migrations = changes.get('<STR_LIT>', [])<EOL>migration = migrations[<NUM_LIT:0>] if len(migrations) > <NUM_LIT:0> else None<EOL>self.migrations.append(migration)<EOL>self.project_state = new_project_state<EOL>return migration<EOL>

Runs the auto-detector and detects changes in
        the project that can be put in a migration.


calls_for_migrations = []<EOL>while len(self.migrations) > <NUM_LIT:0>:<EOL><INDENT>migration = self.migrations.pop()<EOL>with filtered_schema_editor(*filters) as (schema_editor, calls):<EOL><INDENT>migration_executor = MigrationExecutor(schema_editor.connection)<EOL>migration_executor.apply_migration(<EOL>self.project_state, migration<EOL>)<EOL>calls_for_migrations.append(calls)<EOL><DEDENT><DEDENT>return calls_for_migrations<EOL>

Executes the recorded migrations.

Arguments:
    filters: List of strings to filter SQL statements on.

Returns:
    The filtered calls of every migration


project_state = ProjectState()<EOL>for model_state in model_states:<EOL><INDENT>project_state.add_model(model_state.clone())<EOL><DEDENT>return project_state<EOL>

Shortcut to make :see:ProjectState from a list
    of predefined models.


return MigrationAutodetector(<EOL>make_project_state(before_states),<EOL>make_project_state(after_states)<EOL>)._detect_changes()<EOL>

Uses the migration autodetector to detect changes
    in the specified project states.


assert '<STR_LIT>' in changes<EOL>assert len('<STR_LIT>') > <NUM_LIT:0><EOL>operations = changes['<STR_LIT>'][<NUM_LIT:0>].operations<EOL>for i, expected_operation in enumerate(expected):<EOL><INDENT>real_operation = operations[i]<EOL>_, _, real_args, real_kwargs = real_operation.field.deconstruct()<EOL>_, _, expected_args, expected_kwargs = expected_operation.field.deconstruct()<EOL>assert real_args == expected_args<EOL>assert real_kwargs == expected_kwargs<EOL><DEDENT>

Asserts whether the results of the auto detector
    are as expected.


class CustomCommand(BaseCommand):<EOL><INDENT>description = text<EOL>def run(self):<EOL><INDENT>for cmd in commands:<EOL><INDENT>subprocess.check_call(cmd)<EOL><DEDENT><DEDENT><DEDENT>return CustomCommand<EOL>


new_query_values = []<EOL>for field, model, val in self.query.values:<EOL><INDENT>if isinstance(val, dict):<EOL><INDENT>val = HStoreValue(val)<EOL><DEDENT>new_query_values.append((<EOL>field,<EOL>model,<EOL>val<EOL>))<EOL><DEDENT>self.query.values = new_query_values<EOL>

Extra prep on query values by converting
        dictionaries into :see:HStoreValue expressions.

        This allows putting expressions in a dictionary.
        The :see:HStoreValue will take care of resolving
        the expressions inside the dictionary.


qn = self.connection.ops.quote_name<EOL>return '<STR_LIT>' % qn(self.query.model._meta.pk.attname)<EOL>


super().__init__(*args, **kwargs)<EOL>self.qn = self.connection.ops.quote_name<EOL>

Initializes a new instance of :see:PostgresInsertCompiler.


queries = [<EOL>self._rewrite_insert(sql, params, return_id)<EOL>for sql, params in super().as_sql()<EOL>]<EOL>return queries<EOL>


def _rewrite_insert(self, sql, params, return_id=False):

returning = self.qn(self.query.model._meta.pk.attname) if return_id else '<STR_LIT:*>'<EOL>if self.query.conflict_action.value == '<STR_LIT>':<EOL><INDENT>return self._rewrite_insert_update(sql, params, returning)<EOL><DEDENT>elif self.query.conflict_action.value == '<STR_LIT>':<EOL><INDENT>return self._rewrite_insert_nothing(sql, params, returning)<EOL><DEDENT>raise SuspiciousOperation((<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>) % str(self.query.conflict_action))<EOL>

Rewrites a formed SQL INSERT query to include
        the ON CONFLICT clause.

        Arguments:
            sql:
                The SQL INSERT query to rewrite.

            params:
                The parameters passed to the query.

            returning:
                What to put in the `RETURNING` clause
                of the resulting query.

        Returns:
            A tuple of the rewritten SQL query and new params.


def _rewrite_insert_update(self, sql, params, returning):

update_columns = '<STR_LIT:U+002CU+0020>'.join([<EOL>'<STR_LIT>'.format(self.qn(field.column))<EOL>for field in self.query.update_fields<EOL>])<EOL>conflict_target = self._build_conflict_target()<EOL>index_predicate = self.query.index_predicate<EOL>sql_template = (<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>)<EOL>if index_predicate:<EOL><INDENT>sql_template = (<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>)<EOL><DEDENT>return (<EOL>sql_template.format(<EOL>insert=sql,<EOL>conflict_target=conflict_target,<EOL>update_columns=update_columns,<EOL>returning=returning,<EOL>index_predicate=index_predicate,<EOL>),<EOL>params<EOL>)<EOL>

Rewrites a formed SQL INSERT query to include
        the ON CONFLICT DO UPDATE clause.


def _rewrite_insert_nothing(self, sql, params, returning):

<EOL>conflict_target = self._build_conflict_target()<EOL>where_clause = '<STR_LIT>'.join([<EOL>'<STR_LIT>'.format(self._format_field_name(field_name))<EOL>for field_name in self.query.conflict_target<EOL>])<EOL>where_clause_params = [<EOL>self._format_field_value(field_name)<EOL>for field_name in self.query.conflict_target<EOL>]<EOL>params = params + tuple(where_clause_params)<EOL>return (<EOL>(<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>).format(<EOL>insert=sql,<EOL>conflict_target=conflict_target,<EOL>pk_column=self.qn(self.query.model._meta.pk.column),<EOL>returning=returning,<EOL>table=self.query.objs[<NUM_LIT:0>]._meta.db_table,<EOL>where_clause=where_clause<EOL>),<EOL>params<EOL>)<EOL>

Rewrites a formed SQL INSERT query to include
        the ON CONFLICT DO NOTHING clause.


conflict_target = []<EOL>if not isinstance(self.query.conflict_target, list):<EOL><INDENT>raise SuspiciousOperation((<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>) % str(self.query.conflict_target))<EOL><DEDENT>def _assert_valid_field(field_name):<EOL><INDENT>field_name = self._normalize_field_name(field_name)<EOL>if self._get_model_field(field_name):<EOL><INDENT>return<EOL><DEDENT>raise SuspiciousOperation((<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>) % str(field_name))<EOL><DEDENT>for field_name in self.query.conflict_target:<EOL><INDENT>_assert_valid_field(field_name)<EOL>if isinstance(field_name, tuple):<EOL><INDENT>conflict_target.append(<EOL>'<STR_LIT>' % (<EOL>self._format_field_name(field_name),<EOL>field_name[<NUM_LIT:1>]<EOL>)<EOL>)<EOL><DEDENT>else:<EOL><INDENT>conflict_target.append(<EOL>self._format_field_name(field_name))<EOL><DEDENT><DEDENT>return '<STR_LIT>' % '<STR_LIT:U+002C>'.join(conflict_target)<EOL>

Builds the `conflict_target` for the ON CONFLICT
        clause.


field_name = self._normalize_field_name(name)<EOL>if field_name == '<STR_LIT>' and self.query.model._meta.pk:<EOL><INDENT>return self.query.model._meta.pk<EOL><DEDENT>for field in self.query.model._meta.local_concrete_fields:<EOL><INDENT>if field.name == field_name or field.column == field_name:<EOL><INDENT>return field<EOL><DEDENT><DEDENT>return None<EOL>

Gets the field on a model with the specified name.

        Arguments:
            name:
                The name of the field to look for.

                This can be both the actual field name, or
                the name of the column, both will work :)

        Returns:
            The field with the specified name or None if
            no such field exists.


def _format_field_name(self, field_name) -> str:

field = self._get_model_field(field_name)<EOL>return self.qn(field.column)<EOL>

Formats a field's name for usage in SQL.

        Arguments:
            field_name:
                The field name to format.

        Returns:
            The specified field name formatted for
            usage in SQL.


def _format_field_value(self, field_name) -> str:

field_name = self._normalize_field_name(field_name)<EOL>field = self._get_model_field(field_name)<EOL>return SQLInsertCompiler.prepare_value(<EOL>self,<EOL>field,<EOL>getattr(self.query.objs[<NUM_LIT:0>], field.attname)<EOL>)<EOL>

Formats a field's value for usage in SQL.

        Arguments:
            field_name:
                The name of the field to format
                the value of.

        Returns:
            The field's value formatted for usage
            in SQL.


def _normalize_field_name(self, field_name) -> str:

if isinstance(field_name, tuple):<EOL><INDENT>field_name, _ = field_name<EOL><DEDENT>return field_name<EOL>

Normalizes a field name into a string by
        extracting the field name if it was specified
        as a reference to a HStore key (as a tuple).

        Arguments:
            field_name:
                The field name to normalize.

        Returns:
            The normalized field name.


manager = PostgresManager()<EOL>manager.model = model<EOL>yield manager<EOL>

Allows you to use the :see:PostgresManager with
    the specified model instance on the fly.

    Arguments:
        model:
            The model or model instance to use this on.


when_clauses = [<EOL>expressions.When(<EOL>~expressions.Q(**{field: None}),<EOL>then=expressions.F(field)<EOL>)<EOL>for field in reversed(fields)<EOL>]<EOL>return expressions.Case(<EOL>*when_clauses,<EOL>default=expressions.Value(default),<EOL>output_field=CharField()<EOL>)<EOL>

Selects whichever field is not None, in the specified order.

    Arguments:
        fields:
            The fields to attempt to get a value from,
            in order.

        default:
            The value to return in case all values are None.

    Returns:
        A Case-When expression that tries each field and
        returns the specified default value when all of
        them are None.


self.value = value<EOL>


def resolve_expression(self, *args, **kwargs):

result = dict()<EOL>for key, value in self.value.items():<EOL><INDENT>if hasattr(value, '<STR_LIT>'):<EOL><INDENT>result[key] = value.resolve_expression(<EOL>*args, **kwargs)<EOL><DEDENT>else:<EOL><INDENT>result[key] = value<EOL><DEDENT><DEDENT>return HStoreValue(result)<EOL>

Resolves expressions inside the dictionary.


result = []<EOL>for key, value in self.value.items():<EOL><INDENT>if hasattr(value, '<STR_LIT>'):<EOL><INDENT>sql, params = value.as_sql(compiler, connection)<EOL>result.append('<STR_LIT>' % (<EOL>key, sql % params))<EOL><DEDENT>elif value is not None:<EOL><INDENT>result.append('<STR_LIT>' % ((<EOL>key, value)))<EOL><DEDENT>else:<EOL><INDENT>result.append('<STR_LIT>' % key)<EOL><DEDENT><DEDENT>return '<STR_LIT:%s>' % '<STR_LIT>'.join(result), []<EOL>

Compiles the HStore value into SQL.

        Compiles expressions contained in the values
        of HStore entries as well.

        Given a dictionary like:

            dict(key1='val1', key2='val2')

        The resulting SQL will be:

            hstore(hstore('key1', 'val1'), hstore('key2', 'val2'))


def __init__(self, alias, target, hstore_key):

super().__init__(alias, target, output_field=target)<EOL>self.alias, self.target, self.hstore_key = alias, target, hstore_key<EOL>

Initializes a new instance of :see:HStoreColumn.

        Arguments:
            alias:
                The table name.

            target:
                The field instance.

            hstore_key
                The name of the hstore key to include
                in the epxression.


return "<STR_LIT>".format(<EOL>self.__class__.__name__,<EOL>self.alias,<EOL>self.target,<EOL>self.hstore_key<EOL>)<EOL>

Gets a textual representation of this expresion.


qn = compiler.quote_name_unless_alias<EOL>return "<STR_LIT>" % (qn(self.alias), qn(self.target.column), self.hstore_key), []<EOL>


return self.__class__(<EOL>relabels.get(self.alias, self.alias),<EOL>self.target,<EOL>self.hstore_key,<EOL>self.output_field<EOL>)<EOL>

Gets a re-labeled clone of this expression.


def __init__(self, name: str, key: str):

super().__init__(name)<EOL>self.key = key<EOL>

Initializes a new instance of :see:HStoreRef.

        Arguments:
            name:
                The name of the column/field to resolve.

            key:
                The name of the HStore key to select.


def resolve_expression(self, *args, **kwargs) -> HStoreColumn:

original_expression = super().resolve_expression(*args, **kwargs)<EOL>expression = HStoreColumn(<EOL>original_expression.alias,<EOL>original_expression.target,<EOL>self.key<EOL>)<EOL>return expression<EOL>

Resolves the expression into a :see:HStoreColumn expression.


return []<EOL>

Gets the columns to be included in the GROUP BY clause.

        We have to override this because Django's default behavior
        is to include function calls in GROUP by clauses.


sql, params = super().as_sql(compiler, connection)<EOL>return '<STR_LIT>'.format(sql), params<EOL>


def __init__(self, *args,<EOL>uniqueness: List[Union[str, Tuple[str, ...]]]=None,<EOL>required: List[str]=None, **kwargs):

super(HStoreField, self).__init__(*args, **kwargs)<EOL>self.uniqueness = uniqueness<EOL>self.required = required<EOL>

Initializes a new instance of :see:HStoreField.


value = Field.get_prep_value(self, value)<EOL>if isinstance(value, dict):<EOL><INDENT>prep_value = {}<EOL>for key, val in value.items():<EOL><INDENT>if isinstance(val, Expression):<EOL><INDENT>prep_value[key] = val<EOL><DEDENT>elif val is not None:<EOL><INDENT>prep_value[key] = str(val)<EOL><DEDENT>else:<EOL><INDENT>prep_value[key] = val<EOL><DEDENT><DEDENT>value = prep_value<EOL><DEDENT>if isinstance(value, list):<EOL><INDENT>value = [str(item) for item in value]<EOL><DEDENT>return value<EOL>

Override the base class so it doesn't cast all values
        to strings.

        psqlextra supports expressions in hstore fields, so casting
        all values to strings is a bad idea.


name, path, args, kwargs = super(<EOL>HStoreField, self).deconstruct()<EOL>if self.uniqueness is not None:<EOL><INDENT>kwargs['<STR_LIT>'] = self.uniqueness<EOL><DEDENT>if self.required is not None:<EOL><INDENT>kwargs['<STR_LIT>'] = self.required<EOL><DEDENT>return name, path, args, kwargs<EOL>

Gets the values to pass to :see:__init__ when
        re-creating this object.


def __init__(self, model=None, query=None, using=None, hints=None):

super().__init__(model, query, using, hints)<EOL>self.query = query or PostgresQuery(self.model)<EOL>self.conflict_target = None<EOL>self.conflict_action = None<EOL>self.index_predicate = None<EOL>

Initializes a new instance of :see:PostgresQuerySet.


fields = {<EOL>field.name: field<EOL>for field in self.model._meta.get_fields()<EOL>}<EOL>new_annotations = {}<EOL>renames = {}<EOL>for name, value in annotations.items():<EOL><INDENT>if name in fields:<EOL><INDENT>new_name = '<STR_LIT>' % name<EOL>new_annotations[new_name] = value<EOL>renames[new_name] = name<EOL><DEDENT>else:<EOL><INDENT>new_annotations[name] = value<EOL><DEDENT><DEDENT>result = super().annotate(**new_annotations)<EOL>result.rename_annotations(**renames)<EOL>return result<EOL>

Custom version of the standard annotate function
        that allows using field names as annotated fields.

        Normally, the annotate function doesn't allow you
        to use the name of an existing field on the model
        as the alias name. This version of the function does
        allow that.


self.query.rename_annotations(annotations)<EOL>return self<EOL>

Renames the aliases for the specified annotations:

            .annotate(myfield=F('somestuf__myfield'))
            .rename_annotations(myfield='field')

        Arguments:
            annotations:
                The annotations to rename. Mapping the
                old name to the new name.


self.query.add_join_conditions(conditions)<EOL>return self<EOL>

Adds extra conditions to existing joins.

        WARNING: This is an extremely experimental feature.
                 DO NOT USE unless you know what you're doing.


<EOL>self._for_write = True<EOL>if django.VERSION >= (<NUM_LIT:2>, <NUM_LIT:0>):<EOL><INDENT>query = self.query.chain(UpdateQuery)<EOL><DEDENT>else:<EOL><INDENT>query = self.query.clone(UpdateQuery)<EOL><DEDENT>query._annotations = None<EOL>query.add_update_values(fields)<EOL>connection = django.db.connections[self.db]<EOL>compiler = PostgresReturningUpdateCompiler(query, connection, self.db)<EOL>with transaction.atomic(using=self.db, savepoint=False):<EOL><INDENT>rows = compiler.execute_sql(CURSOR)<EOL><DEDENT>self._result_cache = None<EOL>for row in rows:<EOL><INDENT>signals.update.send(self.model, pk=row[<NUM_LIT:0>])<EOL><DEDENT>return len(rows)<EOL>


def on_conflict(self, fields: List[Union[str, Tuple[str]]], action, index_predicate: str=None):

self.conflict_target = fields<EOL>self.conflict_action = action<EOL>self.index_predicate = index_predicate<EOL>return self<EOL>

Sets the action to take when conflicts arise when attempting
        to insert/create a new row.

        Arguments:
            fields:
                The fields the conflicts can occur in.

            action:
                The action to take when the conflict occurs.

            index_predicate:
                The index predicate to satisfy an arbiter partial index (i.e. what partial index to use for checking
                conflicts)


def bulk_insert(self, rows, return_model=False):

if self.conflict_target or self.conflict_action:<EOL><INDENT>compiler = self._build_insert_compiler(rows)<EOL>objs = compiler.execute_sql(return_id=True)<EOL>if return_model:<EOL><INDENT>return [self.model(**dict(r, **k)) for r, k in zip(rows, objs)]<EOL><DEDENT>else:<EOL><INDENT>return [dict(r, **k) for r, k in zip(rows, objs)]<EOL><DEDENT><DEDENT>return super().bulk_create([self.model(**fields) for fields in rows])<EOL>

Creates multiple new records in the database.

        This allows specifying custom conflict behavior using .on_conflict().
        If no special behavior was specified, this uses the normal Django create(..)

        Arguments:
            rows:
                An array of dictionaries, where each dictionary
                describes the fields to insert.

            return_model (default: False):
                If model instances should be returned rather than
                just dicts.

        Returns:
            A list of either the dicts of the rows inserted, including the pk or
            the models of the rows inserted with defaults for any fields not specified


if self.conflict_target or self.conflict_action:<EOL><INDENT>compiler = self._build_insert_compiler([fields])<EOL>rows = compiler.execute_sql(return_id=True)<EOL>pk_field_name = self.model._meta.pk.name<EOL>return rows[<NUM_LIT:0>][pk_field_name]<EOL><DEDENT>return super().create(**fields).pk<EOL>

Creates a new record in the database.

        This allows specifying custom conflict behavior using .on_conflict().
        If no special behavior was specified, this uses the normal Django create(..)

        Arguments:
            fields:
                The fields of the row to create.

        Returns:
            The primary key of the record that was created.


if not self.conflict_target and not self.conflict_action:<EOL><INDENT>return super().create(**fields)<EOL><DEDENT>compiler = self._build_insert_compiler([fields])<EOL>rows = compiler.execute_sql(return_id=False)<EOL>columns = rows[<NUM_LIT:0>]<EOL>model_columns = {}<EOL>for field in self.model._meta.local_concrete_fields:<EOL><INDENT>model_columns[field.column] = field.attname<EOL><DEDENT>model_init_fields = {}<EOL>for column_name, column_value in columns.items():<EOL><INDENT>try:<EOL><INDENT>model_init_fields[model_columns[column_name]] = column_value<EOL><DEDENT>except KeyError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>return self.model(**model_init_fields)<EOL>

Creates a new record in the database and then gets
        the entire row.

        This allows specifying custom conflict behavior using .on_conflict().
        If no special behavior was specified, this uses the normal Django create(..)

        Arguments:
            fields:
                The fields of the row to create.

        Returns:
            The model instance representing the row that was created.


def upsert(self, conflict_target: List, fields: Dict, index_predicate: str=None) -> int:

self.on_conflict(conflict_target, ConflictAction.UPDATE, index_predicate)<EOL>return self.insert(**fields)<EOL>

Creates a new record or updates the existing one
        with the specified data.

        Arguments:
            conflict_target:
                Fields to pass into the ON CONFLICT clause.

            fields:
                Fields to insert/update.

            index_predicate:
                The index predicate to satisfy an arbiter partial index (i.e. what partial index to use for checking
                conflicts)

        Returns:
            The primary key of the row that was created/updated.


def upsert_and_get(self, conflict_target: List, fields: Dict, index_predicate: str=None):

self.on_conflict(conflict_target, ConflictAction.UPDATE, index_predicate)<EOL>return self.insert_and_get(**fields)<EOL>

Creates a new record or updates the existing one
        with the specified data and then gets the row.

        Arguments:
            conflict_target:
                Fields to pass into the ON CONFLICT clause.

            fields:
                Fields to insert/update.

            index_predicate:
                The index predicate to satisfy an arbiter partial index (i.e. what partial index to use for checking
                conflicts)

        Returns:
            The model instance representing the row
            that was created/updated.


def bulk_upsert(self, conflict_target: List, rows: List[Dict], index_predicate: str=None):

if not rows or len(rows) <= <NUM_LIT:0>:<EOL><INDENT>return<EOL><DEDENT>self.on_conflict(conflict_target, ConflictAction.UPDATE, index_predicate)<EOL>return self.bulk_insert(rows)<EOL>

Creates a set of new records or updates the existing
        ones with the specified data.

        Arguments:
            conflict_target:
                Fields to pass into the ON CONFLICT clause.

            rows:
                Rows to upsert.

            index_predicate:
                The index predicate to satisfy an arbiter partial index (i.e. what partial index to use for checking
                conflicts)


def _build_insert_compiler(self, rows: List[Dict]):

<EOL>objs = []<EOL>field_count = len(rows[<NUM_LIT:0>])<EOL>for index, row in enumerate(rows):<EOL><INDENT>if field_count != len(row):<EOL><INDENT>raise SuspiciousOperation((<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>).format(index))<EOL><DEDENT>objs.append(self.model(**row))<EOL><DEDENT>self._for_write = True<EOL>insert_fields, update_fields = self._get_upsert_fields(rows[<NUM_LIT:0>])<EOL>query = PostgresInsertQuery(self.model)<EOL>query.conflict_action = self.conflict_action<EOL>query.conflict_target = self.conflict_target<EOL>query.index_predicate = self.index_predicate<EOL>query.values(objs, insert_fields, update_fields)<EOL>connection = django.db.connections[self.db]<EOL>compiler = PostgresInsertCompiler(query, connection, self.db)<EOL>return compiler<EOL>

Builds the SQL compiler for a insert query.

        Arguments:
            rows:
                A list of dictionaries, where each entry
                describes a record to insert.

        Returns:
            The SQL compiler for the insert.


def _is_magical_field(self, model_instance, field, is_insert: bool):

<EOL>old_value = getattr(model_instance, field.name, None)<EOL>field.pre_save(model_instance, is_insert)<EOL>new_value = getattr(model_instance, field.name, None)<EOL>return old_value != new_value<EOL>

Verifies whether this field is gonna modify something
        on its own.

        "Magical" means that a field modifies the field value
        during the pre_save.

        Arguments:
            model_instance:
                The model instance the field is defined on.

            field:
                The field to get of whether the field is
                magical.

            is_insert:
                Pretend whether this is an insert?

        Returns:
            True when this field modifies something.


model_instance = self.model(**kwargs)<EOL>insert_fields = []<EOL>update_fields = []<EOL>for field in model_instance._meta.local_concrete_fields:<EOL><INDENT>has_default = field.default != NOT_PROVIDED<EOL>if (field.name in kwargs or field.column in kwargs):<EOL><INDENT>insert_fields.append(field)<EOL>update_fields.append(field)<EOL>continue<EOL><DEDENT>elif has_default:<EOL><INDENT>insert_fields.append(field)<EOL>continue<EOL><DEDENT>if field.primary_key is True and '<STR_LIT>' in kwargs:<EOL><INDENT>insert_fields.append(field)<EOL>update_fields.append(field)<EOL>continue<EOL><DEDENT>if self._is_magical_field(model_instance, field, is_insert=True):<EOL><INDENT>insert_fields.append(field)<EOL><DEDENT>if self._is_magical_field(model_instance, field, is_insert=False):<EOL><INDENT>update_fields.append(field)<EOL><DEDENT><DEDENT>return insert_fields, update_fields<EOL>

Gets the fields to use in an upsert.

        This some nice magic. We'll split the fields into
        a group of "insert fields" and "update fields":

        INSERT INTO bla ("val1", "val2") ON CONFLICT DO UPDATE SET val1 = EXCLUDED.val1

                         ^^^^^^^^^^^^^^                            ^^^^^^^^^^^^^^^^^^^^
                         insert_fields                                 update_fields

        Often, fields appear in both lists. But, for example,
        a :see:DateTime field with `auto_now_add=True` set, will
        only appear in "insert_fields", since it won't be set
        on existing rows.

        Other than that, the user specificies a list of fields
        in the upsert() call. That migt not be all fields. The
        user could decide to leave out optional fields. If we
        end up doing an update, we don't want to overwrite
        those non-specified fields.

        We cannot just take the list of fields the user
        specifies, because as mentioned, some fields
        make modifications to the model on their own.

        We'll have to detect which fields make modifications
        and include them in the list of insert/update fields.


super(PostgresManager, self).__init__(*args, **kwargs)<EOL>db_backend = settings.DATABASES['<STR_LIT:default>']['<STR_LIT>']<EOL>if '<STR_LIT>' not in db_backend:<EOL><INDENT>raise ImproperlyConfigured((<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>) % db_backend)<EOL><DEDENT>django.db.models.signals.post_save.connect(<EOL>self._on_model_save, sender=self.model, weak=False)<EOL>django.db.models.signals.pre_delete.connect(<EOL>self._on_model_delete, sender=self.model, weak=False)<EOL>self._signals_connected = True<EOL>

Initializes a new instance of :see:PostgresManager.


if self._signals_connected is False:<EOL><INDENT>return<EOL><DEDENT>


return PostgresQuerySet(self.model, using=self._db)<EOL>

Gets the query set to be used on this manager.


return self.get_queryset().on_conflict(fields, action, index_predicate)<EOL>

Sets the action to take when conflicts arise when attempting
        to insert/create a new row.

        Arguments:
            fields:
                The fields the conflicts can occur in.

            action:
                The action to take when the conflict occurs.

            index_predicate:
                The index predicate to satisfy an arbiter partial index.


return self.get_queryset().upsert(conflict_target, fields, index_predicate)<EOL>

Creates a new record or updates the existing one
        with the specified data.

        Arguments:
            conflict_target:
                Fields to pass into the ON CONFLICT clause.

            fields:
                Fields to insert/update.

            index_predicate:
                The index predicate to satisfy an arbiter partial index.

        Returns:
            The primary key of the row that was created/updated.


return self.get_queryset().upsert_and_get(conflict_target, fields, index_predicate)<EOL>

Creates a new record or updates the existing one
        with the specified data and then gets the row.

        Arguments:
            conflict_target:
                Fields to pass into the ON CONFLICT clause.

            fields:
                Fields to insert/update.

            index_predicate:
                The index predicate to satisfy an arbiter partial index.

        Returns:
            The model instance representing the row
            that was created/updated.


return self.get_queryset().bulk_upsert(conflict_target, rows, index_predicate)<EOL>

Creates a set of new records or updates the existing
        ones with the specified data.

        Arguments:
            conflict_target:
                Fields to pass into the ON CONFLICT clause.

            index_predicate:
                The index predicate to satisfy an arbiter partial index.

            rows:
                Rows to upsert.


created, instance = kwargs['<STR_LIT>'], kwargs['<STR_LIT>']<EOL>if created:<EOL><INDENT>signals.create.send(sender, pk=instance.pk)<EOL><DEDENT>else:<EOL><INDENT>signals.update.send(sender, pk=instance.pk)<EOL><DEDENT>


instance = kwargs['<STR_LIT>']<EOL>signals.delete.send(sender, pk=instance.pk)<EOL>


super().__init__(*args, **kwargs)<EOL>self.join_type = '<STR_LIT>'<EOL>self.extra_conditions = []<EOL>

Initializes a new instance of :see:ConditionalJoin.


def add_condition(self, field, value: Any) -> None:

self.extra_conditions.append((field, value))<EOL>

Adds an extra condition to this join.

        Arguments:
            field:
                The field that the condition will apply to.

            value:
                The value to compare.


def as_sql(self, compiler, connection) -> Tuple[str, List[Any]]:

sql, params = super().as_sql(compiler, connection)<EOL>qn = compiler.quote_name_unless_alias<EOL>extra_conditions = '<STR_LIT>'.join([<EOL>'<STR_LIT>'.format(<EOL>qn(self.table_name),<EOL>qn(field.column)<EOL>)<EOL>for field, value in self.extra_conditions<EOL>])<EOL>for _, value in self.extra_conditions:<EOL><INDENT>params.append(value)<EOL><DEDENT>rewritten_sql = sql.replace('<STR_LIT:)>', '<STR_LIT>'.format(extra_conditions))<EOL>return rewritten_sql, params<EOL>


@classmethod<EOL><INDENT>def from_join(cls, join: Join) -> '<STR_LIT>':<DEDENT>

return cls(<EOL>join.table_name,<EOL>join.parent_alias,<EOL>join.table_alias,<EOL>join.join_type,<EOL>join.join_field,<EOL>join.nullable<EOL>)<EOL>

Creates a new :see:ConditionalJoin from the
        specified :see:Join object.

        Arguments:
            join:
                The :see:Join object to create the
                :see:ConditionalJoin object from.

        Returns:
            A :see:ConditionalJoin object created from
            the :see:Join object.


def rename_annotations(self, annotations) -> None:

for old_name, new_name in annotations.items():<EOL><INDENT>annotation = self.annotations.get(old_name)<EOL>if not annotation:<EOL><INDENT>raise SuspiciousOperation((<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>).format(old_name=old_name, new_name=new_name))<EOL><DEDENT>self._annotations = OrderedDict(<EOL>[(new_name, v) if k == old_name else (k, v) for k, v in self._annotations.items()])<EOL>if django.VERSION < (<NUM_LIT:2>, <NUM_LIT:0>):<EOL><INDENT>self.set_annotation_mask(<EOL>(new_name if v == old_name else v for v in (self.annotation_select_mask or [])))<EOL><DEDENT><DEDENT>

Renames the aliases for the specified annotations:

            .annotate(myfield=F('somestuf__myfield'))
            .rename_annotations(myfield='field')

        Arguments:
            annotations:
                The annotations to rename. Mapping the
                old name to the new name.


def add_join_conditions(self, conditions: Dict[str, Any]) -> None:

alias = self.get_initial_alias()<EOL>opts = self.get_meta()<EOL>for name, value in conditions.items():<EOL><INDENT>parts = name.split(LOOKUP_SEP)<EOL>join_info = self.setup_joins(parts, opts, alias, allow_many=True)<EOL>self.trim_joins(join_info[<NUM_LIT:1>], join_info[<NUM_LIT:3>], join_info[<NUM_LIT:4>])<EOL>target_table = join_info[<NUM_LIT:3>][-<NUM_LIT:1>]<EOL>field = join_info[<NUM_LIT:1>][-<NUM_LIT:1>]<EOL>join = self.alias_map.get(target_table)<EOL>if not join:<EOL><INDENT>raise SuspiciousOperation((<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'<EOL>) % target_table)<EOL><DEDENT>if not isinstance(join, ConditionalJoin):<EOL><INDENT>self.alias_map[target_table] = ConditionalJoin.from_join(join)<EOL>join = self.alias_map[target_table]<EOL><DEDENT>join.add_condition(field, value)<EOL><DEDENT>

Adds an extra condition to an existing JOIN.

        This allows you to for example do:

            INNER JOIN othertable ON (mytable.id = othertable.other_id AND [extra conditions])

        This does not work if nothing else in your query doesn't already generate the
        initial join in the first place.


def add_fields(self, field_names: List[str], allow_m2m: bool=True) -> bool:

alias = self.get_initial_alias()<EOL>opts = self.get_meta()<EOL>cols = []<EOL>for name in field_names:<EOL><INDENT>parts = name.split(LOOKUP_SEP)<EOL>if len(parts) > <NUM_LIT:1>:<EOL><INDENT>column_name, hstore_key = parts[:<NUM_LIT:2>]<EOL>is_hstore, field = self._is_hstore_field(column_name)<EOL>if is_hstore:<EOL><INDENT>cols.append(<EOL>HStoreColumn(self.model._meta.db_table or self.model.name, field, hstore_key)<EOL>)<EOL>continue<EOL><DEDENT><DEDENT>join_info = self.setup_joins(parts, opts, alias, allow_many=allow_m2m)<EOL>targets, final_alias, joins = self.trim_joins(<EOL>join_info[<NUM_LIT:1>], join_info[<NUM_LIT:3>], join_info[<NUM_LIT:4>]<EOL>)<EOL>for target in targets:<EOL><INDENT>cols.append(target.get_col(final_alias))<EOL><DEDENT><DEDENT>if cols:<EOL><INDENT>self.set_select(cols)<EOL><DEDENT>

Adds the given (model) fields to the select set. The field names are
added in the order specified.

This overrides the base class's add_fields method. This is called by
the .values() or .values_list() method of the query set. It instructs
the ORM to only select certain values. A lot of processing is neccesarry
because it can be used to easily do joins. For example, `my_fk__name` pulls
in the `name` field in foreign key `my_fk`.

In our case, we want to be able to do `title__en`, where `title` is a HStoreField
and `en` a key. This doesn't really involve a join. We iterate over the specified
field names and filter out the ones that refer to HStoreField and compile it into
an expression which is added to the list of to be selected fields using `self.add_select`.


def _is_hstore_field(self, field_name: str) -> Tuple[bool, Optional[models.Field]]:

field_instance = None<EOL>for field in self.model._meta.local_concrete_fields:<EOL><INDENT>if field.name == field_name or field.column == field_name:<EOL><INDENT>field_instance = field<EOL>break<EOL><DEDENT><DEDENT>return isinstance(field_instance, HStoreField), field_instance<EOL>

Gets whether the field with the specified name is a
        HStoreField.

        Returns
            A tuple of a boolean indicating whether the field
            with the specified name is a HStoreField, and the
            field instance.


super(PostgresInsertQuery, self).__init__(*args, **kwargs)<EOL>self.conflict_target = []<EOL>self.conflict_action = ConflictAction.UPDATE<EOL>self.update_fields = []<EOL>

Initializes a new instance :see:PostgresInsertQuery.


def values(self, objs: List, insert_fields: List, update_fields: List=[]):

self.insert_values(insert_fields, objs, raw=False)<EOL>self.update_fields = update_fields<EOL>

Sets the values to be used in this query.

        Insert fields are fields that are definitely
        going to be inserted, and if an existing row
        is found, are going to be overwritten with the
        specified value.

        Update fields are fields that should be overwritten
        in case an update takes place rather than an insert.
        If we're dealing with a INSERT, these will not be used.

        Arguments:
            objs:
                The objects to apply this query to.

            insert_fields:
                The fields to use in the INSERT statement

            update_fields:
                The fields to only use in the UPDATE statement.


def __init__(self, condition: str, fields=[], name=None):

super().__init__(fields=fields, name=name)<EOL>self.condition = condition<EOL>

Initializes a new instance of :see:ConditionalUniqueIndex.


def create_sql(self, model, schema_editor, using='<STR_LIT>'):

if django.VERSION >= (<NUM_LIT:2>, <NUM_LIT:0>):<EOL><INDENT>statement = super().create_sql(model, schema_editor, using)<EOL>statement.template = self.sql_create_index<EOL>statement.parts['<STR_LIT>'] = self.condition<EOL>return statement<EOL><DEDENT>else:<EOL><INDENT>sql_create_index = self.sql_create_index<EOL>sql_parameters = {<EOL>**Index.get_sql_create_template_values(self, model, schema_editor, using),<EOL>'<STR_LIT>': self.condition<EOL>}<EOL>return sql_create_index % sql_parameters<EOL><DEDENT>

Creates the actual SQL used when applying the migration.


path = '<STR_LIT>' % (self.__class__.__module__, self.__class__.__name__)<EOL>path = path.replace('<STR_LIT>', '<STR_LIT>')<EOL>return path, (), {'<STR_LIT>': self.fields, '<STR_LIT:name>': self.name, '<STR_LIT>': self.condition}<EOL>

Serializes the :see:ConditionalUniqueIndex for the migrations file.


for field in model._meta.local_fields:<EOL><INDENT>if not isinstance(field, HStoreField):<EOL><INDENT>continue<EOL><DEDENT>self.add_field(model, field)<EOL><DEDENT>


for field in model._meta.local_fields:<EOL><INDENT>if not isinstance(field, HStoreField):<EOL><INDENT>continue<EOL><DEDENT>self.remove_field(model, field)<EOL><DEDENT>


def alter_db_table(self, model, old_db_table, new_db_table):

for field in model._meta.local_fields:<EOL><INDENT>if not isinstance(field, HStoreField):<EOL><INDENT>continue<EOL><DEDENT>for key in self._iterate_required_keys(field):<EOL><INDENT>self._rename_hstore_required(<EOL>old_db_table,<EOL>new_db_table,<EOL>field,<EOL>field,<EOL>key<EOL>)<EOL><DEDENT><DEDENT>

Ran when the name of a model is changed.


for key in self._iterate_required_keys(field):<EOL><INDENT>self._create_hstore_required(<EOL>model._meta.db_table,<EOL>field,<EOL>key<EOL>)<EOL><DEDENT>


for key in self._iterate_required_keys(field):<EOL><INDENT>self._drop_hstore_required(<EOL>model._meta.db_table,<EOL>field,<EOL>key<EOL>)<EOL><DEDENT>

Ran when a field is removed from a model.


def alter_field(self, model, old_field, new_field, strict=False):

is_old_field_hstore = isinstance(old_field, HStoreField)<EOL>is_new_field_hstore = isinstance(new_field, HStoreField)<EOL>if not is_old_field_hstore and not is_new_field_hstore:<EOL><INDENT>return<EOL><DEDENT>old_required = getattr(old_field, '<STR_LIT>', []) or []<EOL>new_required = getattr(new_field, '<STR_LIT>', []) or []<EOL>if str(old_field.column) != str(new_field.column):<EOL><INDENT>for key in self._iterate_required_keys(old_field):<EOL><INDENT>self._rename_hstore_required(<EOL>model._meta.db_table,<EOL>model._meta.db_table,<EOL>old_field,<EOL>new_field,<EOL>key<EOL>)<EOL><DEDENT><DEDENT>for key in old_required:<EOL><INDENT>if key not in new_required:<EOL><INDENT>self._drop_hstore_required(<EOL>model._meta.db_table,<EOL>old_field,<EOL>key<EOL>)<EOL><DEDENT><DEDENT>for key in new_required:<EOL><INDENT>if key not in old_required:<EOL><INDENT>self._create_hstore_required(<EOL>model._meta.db_table,<EOL>new_field,<EOL>key<EOL>)<EOL><DEDENT><DEDENT>

Ran when the configuration on a field changed.


def _create_hstore_required(self, table_name, field, key):

name = self._required_constraint_name(<EOL>table_name, field, key)<EOL>sql = self.sql_hstore_required_create.format(<EOL>name=self.quote_name(name),<EOL>table=self.quote_name(table_name),<EOL>field=self.quote_name(field.column),<EOL>key=key<EOL>)<EOL>self.execute(sql)<EOL>

Creates a REQUIRED CONSTRAINT for the specified hstore key.


def _rename_hstore_required(self, old_table_name, new_table_name,<EOL>old_field, new_field, key):

old_name = self._required_constraint_name(<EOL>old_table_name, old_field, key)<EOL>new_name = self._required_constraint_name(<EOL>new_table_name, new_field, key)<EOL>sql = self.sql_hstore_required_rename.format(<EOL>table=self.quote_name(new_table_name),<EOL>old_name=self.quote_name(old_name),<EOL>new_name=self.quote_name(new_name)<EOL>)<EOL>self.execute(sql)<EOL>

Renames an existing REQUIRED CONSTRAINT for the specified
        hstore key.


def _drop_hstore_required(self, table_name, field, key):

name = self._required_constraint_name(<EOL>table_name, field, key)<EOL>sql = self.sql_hstore_required_drop.format(<EOL>table=self.quote_name(table_name),<EOL>name=self.quote_name(name)<EOL>)<EOL>self.execute(sql)<EOL>

Drops a REQUIRED CONSTRAINT for the specified hstore key.


@staticmethod<EOL><INDENT>def _required_constraint_name(table: str, field, key):<DEDENT>

return '<STR_LIT>'.format(<EOL>table=table,<EOL>field=field.column,<EOL>postfix=key<EOL>)<EOL>

Gets the name for a CONSTRAINT that applies
        to a single hstore key.

        Arguments:
            table:
                The name of the table the field is
                a part of.

            field:
                The hstore field to create a
                UNIQUE INDEX for.

            key:
                The name of the hstore key
                to create the name for.

        Returns:
            The name for the UNIQUE index.


required_keys = getattr(field, '<STR_LIT>', None)<EOL>if not required_keys:<EOL><INDENT>return<EOL><DEDENT>for key in required_keys:<EOL><INDENT>yield key<EOL><DEDENT>

Iterates over the keys marked as "required"
        in the specified field.

        Arguments:
            field:
                The field of which key's to
                iterate over.


for field in model._meta.local_fields:<EOL><INDENT>if not isinstance(field, HStoreField):<EOL><INDENT>continue<EOL><DEDENT>for keys in self._iterate_uniqueness_keys(field):<EOL><INDENT>self._rename_hstore_unique(<EOL>old_db_table,<EOL>new_db_table,<EOL>field,<EOL>field,<EOL>keys<EOL>)<EOL><DEDENT><DEDENT>


for keys in self._iterate_uniqueness_keys(field):<EOL><INDENT>self._create_hstore_unique(<EOL>model,<EOL>field,<EOL>keys<EOL>)<EOL><DEDENT>


for keys in self._iterate_uniqueness_keys(field):<EOL><INDENT>self._drop_hstore_unique(<EOL>model,<EOL>field,<EOL>keys<EOL>)<EOL><DEDENT>


is_old_field_hstore = isinstance(old_field, HStoreField)<EOL>is_new_field_hstore = isinstance(new_field, HStoreField)<EOL>if not is_old_field_hstore and not is_new_field_hstore:<EOL><INDENT>return<EOL><DEDENT>old_uniqueness = getattr(old_field, '<STR_LIT>', []) or []<EOL>new_uniqueness = getattr(new_field, '<STR_LIT>', []) or []<EOL>if str(old_field.column) != str(new_field.column):<EOL><INDENT>for keys in self._iterate_uniqueness_keys(old_field):<EOL><INDENT>self._rename_hstore_unique(<EOL>model._meta.db_table,<EOL>model._meta.db_table,<EOL>old_field,<EOL>new_field,<EOL>keys<EOL>)<EOL><DEDENT><DEDENT>for keys in old_uniqueness:<EOL><INDENT>if keys not in new_uniqueness:<EOL><INDENT>self._drop_hstore_unique(<EOL>model,<EOL>old_field,<EOL>self._compose_keys(keys)<EOL>)<EOL><DEDENT><DEDENT>for keys in new_uniqueness:<EOL><INDENT>if keys not in old_uniqueness:<EOL><INDENT>self._create_hstore_unique(<EOL>model,<EOL>new_field,<EOL>self._compose_keys(keys)<EOL>)<EOL><DEDENT><DEDENT>


def _create_hstore_unique(self, model, field, keys):

name = self._unique_constraint_name(<EOL>model._meta.db_table, field, keys)<EOL>columns = [<EOL>'<STR_LIT>' % (field.column, key)<EOL>for key in keys<EOL>]<EOL>sql = self.sql_hstore_unique_create.format(<EOL>name=self.quote_name(name),<EOL>table=self.quote_name(model._meta.db_table),<EOL>columns='<STR_LIT:U+002C>'.join(columns)<EOL>)<EOL>self.execute(sql)<EOL>

Creates a UNIQUE constraint for the specified hstore keys.


def _rename_hstore_unique(self, old_table_name, new_table_name,<EOL>old_field, new_field, keys):

old_name = self._unique_constraint_name(<EOL>old_table_name, old_field, keys)<EOL>new_name = self._unique_constraint_name(<EOL>new_table_name, new_field, keys)<EOL>sql = self.sql_hstore_unique_rename.format(<EOL>old_name=self.quote_name(old_name),<EOL>new_name=self.quote_name(new_name)<EOL>)<EOL>self.execute(sql)<EOL>

Renames an existing UNIQUE constraint for the specified
        hstore keys.


def _drop_hstore_unique(self, model, field, keys):

name = self._unique_constraint_name(<EOL>model._meta.db_table, field, keys)<EOL>sql = self.sql_hstore_unique_drop.format(name=self.quote_name(name))<EOL>self.execute(sql)<EOL>

Drops a UNIQUE constraint for the specified hstore keys.


@staticmethod<EOL><INDENT>def _unique_constraint_name(table: str, field, keys):<DEDENT>

postfix = '<STR_LIT:_>'.join(keys)<EOL>return '<STR_LIT>'.format(<EOL>table=table,<EOL>field=field.column,<EOL>postfix=postfix<EOL>)<EOL>

Gets the name for a UNIQUE INDEX that applies
        to one or more keys in a hstore field.

        Arguments:
            table:
                The name of the table the field is
                a part of.

            field:
                The hstore field to create a
                UNIQUE INDEX for.

            key:
                The name of the hstore key
                to create the name for.

                This can also be a tuple
                of multiple names.

        Returns:
            The name for the UNIQUE index.


uniqueness = getattr(field, '<STR_LIT>', None)<EOL>if not uniqueness:<EOL><INDENT>return<EOL><DEDENT>for keys in uniqueness:<EOL><INDENT>composed_keys = self._compose_keys(keys)<EOL>yield composed_keys<EOL><DEDENT>

Iterates over the keys marked as "unique"
        in the specified field.

        Arguments:
            field:
                The field of which key's to
                iterate over.


if isinstance(constraint, str):<EOL><INDENT>return [constraint]<EOL><DEDENT>return constraint<EOL>

Turns a string into a list of string or
        returns it as a list.