if isinstance(image, string_types):<EOL><INDENT>img = open_volume_file(image)<EOL>if make_it_3d:<EOL><INDENT>img = _make_it_3d(img)<EOL><DEDENT>return img<EOL><DEDENT>elif isinstance(image, np.array):<EOL><INDENT>return nib.Nifti2Image(image, affine=np.eye(image.ndim + <NUM_LIT:1>))<EOL><DEDENT>elif isinstance(image, nib.Nifti1Image) or is_img(image):<EOL><INDENT>return image<EOL><DEDENT>else:<EOL><INDENT>raise TypeError('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>'.format(type(image)))<EOL><DEDENT>

Check that image is a proper img. Turn filenames into objects.

    Parameters
    ----------
    image: img-like object or str
        Can either be:
        - a file path to a medical image file, e.g. NifTI, .mhd/raw, .mha
        - any object with get_data() method and affine & header attributes, e.g., nibabel.Nifti1Image.
        - a Numpy array, which will be wrapped by a nibabel.Nifti2Image class with an `eye` affine.
        If niimg is a string, consider it as a path to Nifti image and
        call nibabel.load on it. If it is an object, check if get_data()
        and get_affine() methods are present, raise TypeError otherwise.

    make_it_3d: boolean, optional
        If True, check if the image is a 3D image and raise an error if not.

    Returns
    -------
    result: nifti-like
       result can be nibabel.Nifti1Image or the input, as-is. It is guaranteed
       that the returned object has get_data() and get_affine() methods.


updated_msg = msg<EOL>for k, v in sorted(kwargs.items()):<EOL><INDENT>if isinstance(v, _basestring):  <EOL><INDENT>updated_msg += "<STR_LIT:\n>" + k + "<STR_LIT>" + v<EOL><DEDENT><DEDENT>return updated_msg<EOL>

Append key-value pairs to msg, for display.

    Parameters
    ----------
    msg: string
        arbitrary message
    kwargs: dict
        arbitrary dictionary

    Returns
    -------
    updated_msg: string
        msg, with "key: value" appended. Only string values are appended.

    Example
    -------
    >>> compose_err_msg('Error message with arguments...', arg_num=123, \
        arg_str='filename.nii', arg_bool=True)
    'Error message with arguments...\\narg_str: filename.nii'
    >>>


utc = tzutc()<EOL>if dt.tzinfo:<EOL><INDENT>dt = dt.astimezone(utc).replace(tzinfo=None)<EOL><DEDENT>return dt.isoformat() + '<STR_LIT>'<EOL>

Serialize a date/time value into an ISO8601 text representation
adjusted (if needed) to UTC timezone.

For instance:
>>> serialize_date(datetime(2012, 4, 10, 22, 38, 20, 604391))
'2012-04-10T22:38:20.604391Z'


return str(dt.date())<EOL>

Serialize a date/time value into YYYY-MM-DD date string.


sdata = data.copy()<EOL>for k, v in data.items():<EOL><INDENT>if isinstance(v, datetime):<EOL><INDENT>sdata[k] = timestamp_to_date_str(v)<EOL><DEDENT>elif not isinstance(v, (string_types, float, int)):<EOL><INDENT>sdata[k] = str(v)<EOL><DEDENT><DEDENT>return sdata<EOL>

Convert to string all values in `data`.

    Parameters
    ----------
    data: dict[str]->object

    Returns
    -------
    string_data: dict[str]->str


def insert_unique(table, data, unique_fields=None, *, raise_if_found=False):

item = find_unique(table, data, unique_fields)<EOL>if item is not None:<EOL><INDENT>if raise_if_found:<EOL><INDENT>raise NotUniqueItemError('<STR_LIT>'<EOL>'<STR_LIT>'.format(unique_fields,<EOL>data,<EOL>table.get(eid=item),<EOL>item))<EOL><DEDENT>else:<EOL><INDENT>return item<EOL><DEDENT><DEDENT>return table.insert(data)<EOL>

Insert `data` into `table` ensuring that data has unique values
    in `table` for the fields listed in `unique_fields`.

    If `raise_if_found` is True, will raise an NotUniqueItemError if
    another item with the same `unique_fields` values are found
    previously in `table`.
    If False, will return the `eid` from the item found.

    Parameters
    ----------
    table: tinydb.Table

    data: dict

    unique_fields: list of str
        Name of fields (keys) from `data` which are going to be used to build
        a sample to look for exactly the same values in the database.
        If None, will use every key in `data`.

    raise_if_found: bool

    Returns
    -------
    eid: int
        Id of the object inserted or the one found with same `unique_fields`.

    Raises
    ------
    MoreThanOneItemError
        Raise even with `raise_with_found` == False if it finds more than one item
        with the same values as the sample.

    NotUniqueItemError
        If `raise_if_found` is True and an item with the same `unique_fields`
        values from `data` is found in `table`.


query = _query_sample(sample=sample, operators='<STR_LIT>')<EOL>return table.search(query)<EOL>

Search for items in `table` that have the same field sub-set values as in `sample`.

    Parameters
    ----------
    table: tinydb.table

    sample: dict
        Sample data

    Returns
    -------
    search_result: list of dict
        List of the items found. The list is empty if no item is found.


def search_unique(table, sample, unique_fields=None):

if unique_fields is None:<EOL><INDENT>unique_fields = list(sample.keys())<EOL><DEDENT>query = _query_data(sample, field_names=unique_fields, operators='<STR_LIT>')<EOL>items = table.search(query)<EOL>if len(items) == <NUM_LIT:1>:<EOL><INDENT>return items[<NUM_LIT:0>]<EOL><DEDENT>if len(items) == <NUM_LIT:0>:<EOL><INDENT>return None<EOL><DEDENT>raise MoreThanOneItemError('<STR_LIT>'<EOL>'<STR_LIT>'.format(len(items)))<EOL>

Search for items in `table` that have the same field sub-set values as in `sample`.
    Expecting it to be unique, otherwise will raise an exception.

    Parameters
    ----------
    table: tinydb.table
    sample: dict
        Sample data

    Returns
    -------
    search_result: tinydb.database.Element
        Unique item result of the search.

    Raises
    ------
    KeyError:
        If the search returns for more than one entry.


def find_unique(table, sample, unique_fields=None):

res = search_unique(table, sample, unique_fields)<EOL>if res is not None:<EOL><INDENT>return res.eid<EOL><DEDENT>else:<EOL><INDENT>return res<EOL><DEDENT>

Search in `table` an item with the value of the `unique_fields` in the `sample` sample.
    Check if the the obtained result is unique. If nothing is found will return an empty list,
    if there is more than one item found, will raise an IndexError.

    Parameters
    ----------
    table: tinydb.table

    sample: dict
        Sample data

    unique_fields: list of str
        Name of fields (keys) from `data` which are going to be used to build
        a sample to look for exactly the same values in the database.
        If None, will use every key in `data`.

    Returns
    -------
    eid: int
        Id of the object found with same `unique_fields`.
        None if none is found.

    Raises
    ------
    MoreThanOneItemError
        If more than one example is found.


if isinstance(operators, str):<EOL><INDENT>operators = [operators] * len(sample)<EOL><DEDENT>if len(sample) != len(operators):<EOL><INDENT>raise ValueError('<STR_LIT>'<EOL>'<STR_LIT>'.format(len(sample),<EOL>operators))<EOL><DEDENT>queries = []<EOL>for i, fn in enumerate(sample):<EOL><INDENT>fv = sample[fn]<EOL>op = operators[i]<EOL>queries.append(_build_query(field_name=fn,<EOL>field_value=fv,<EOL>operator=op))<EOL><DEDENT>return _concat_queries(queries, operators='<STR_LIT>')<EOL>

Create a TinyDB query that looks for items that have each field in `sample` with a value
    compared with the correspondent operation in `operators`.

    Parameters
    ----------
    sample: dict
        The sample data

    operators: str or list of str
        A list of comparison operations for each field value in `sample`.
        If this is a str, will use the same operator for all `sample` fields.
        If you want different operators for each field, remember to use an OrderedDict for `sample`.
        Check TinyDB.Query class for possible choices.

    Returns
    -------
    query: tinydb.database.Query


def _query_data(data, field_names=None, operators='<STR_LIT>'):

if field_names is None:<EOL><INDENT>field_names = list(data.keys())<EOL><DEDENT>if isinstance(field_names, str):<EOL><INDENT>field_names = [field_names]<EOL><DEDENT>sample = OrderedDict([(fn, data[fn]) for fn in field_names])<EOL>return _query_sample(sample, operators=operators)<EOL>

Create a tinyDB Query object that looks for items that confirms the correspondent operator
    from `operators` for each `field_names` field values from `data`.

    Parameters
    ----------
    data: dict
        The data sample

    field_names: str or list of str
        The name of the fields in `data` that will be used for the query.

    operators: str or list of str
        A list of comparison operations for each field value in `field_names`.
        If this is a str, will use the same operator for all `field_names`.
        If you want different operators for each field, remember to use an OrderedDict for `data`.
        Check TinyDB.Query class for possible choices.

    Returns
    -------
    query: tinydb.database.Query


<EOL>if not queries:<EOL><INDENT>raise ValueError('<STR_LIT>'.format(queries))<EOL><DEDENT>if len(queries) == <NUM_LIT:1>:<EOL><INDENT>return queries[<NUM_LIT:0>]<EOL><DEDENT>if isinstance(operators, str):<EOL><INDENT>operators = [operators] * (len(queries) - <NUM_LIT:1>)<EOL><DEDENT>if len(queries) - <NUM_LIT:1> != len(operators):<EOL><INDENT>raise ValueError('<STR_LIT>'<EOL>'<STR_LIT>'.format(len(queries),<EOL>operators))<EOL><DEDENT>first, rest, end = queries[<NUM_LIT:0>], queries[<NUM_LIT:1>:-<NUM_LIT:1>], queries[-<NUM_LIT:1>:][<NUM_LIT:0>]<EOL>bigop = getattr(first, operators[<NUM_LIT:0>])<EOL>for i, q in enumerate(rest):<EOL><INDENT>bigop = getattr(bigop(q), operators[i])<EOL><DEDENT>return bigop(end)<EOL>

Create a tinyDB Query object that is the concatenation of each query in `queries`.
    The concatenation operator is taken from `operators`.

    Parameters
    ----------
    queries: list of tinydb.Query
        The list of tinydb.Query to be joined.

    operators: str or list of str
        List of binary operators to join `queries` into one query.
        Check TinyDB.Query class for possible choices.

    Returns
    -------
    query: tinydb.database.Query


def _build_query(field_name, field_value, operator='<STR_LIT>'):

qelem = where(field_name)<EOL>if not hasattr(qelem, operator):<EOL><INDENT>raise NotImplementedError('<STR_LIT>'.format(operator))<EOL><DEDENT>else:<EOL><INDENT>query = getattr(qelem, operator)<EOL><DEDENT>return query(field_value)<EOL>

Create a tinyDB Query object with the format:
    (where(`field_name`) `operator` `field_value`)

    Parameters
    ----------
    field_name: str
        The name of the field to be queried.

    field_value:
        The value of the field

    operator: str
        The comparison operator.
        Check TinyDB.Query class for possible choices.

    Returns
    -------
    query: tinydb.database.Query


def search_by_eid(self, table_name, eid):

elem = self.table(table_name).get(eid=eid)<EOL>if elem is None:<EOL><INDENT>raise KeyError('<STR_LIT>'.format(table_name, eid))<EOL><DEDENT>return elem<EOL>

Return the element in `table_name` with Object ID `eid`.
        If None is found will raise a KeyError exception.

        Parameters
        ----------
        table_name: str
            The name of the table to look in.

        eid: int
            The Object ID of the element to look for.

        Returns
        -------
        elem: tinydb.database.Element

        Raises
        ------
        KeyError
            If the element with ID `eid` is not found.


def insert_unique(self, table_name, data, unique_fields=None, *, raise_if_found=False):

return insert_unique(table=self.table(table_name),<EOL>data=_to_string(data),<EOL>unique_fields=unique_fields,<EOL>raise_if_found=raise_if_found)<EOL>

Insert `data` into `table` ensuring that data has unique values
        in `table` for the fields listed in `unique_fields`.

        If `raise_if_found` is True, will raise an NotUniqueItemError if
        another item with the same `unique_fields` values are found
        previously in `table`.
        If False, will return the `eid` from the item found.

        Parameters
        ----------
        table_name: str

        data: dict

        unique_fields: list of str
            Name of fields (keys) from `data` which are going to be used to build
            a sample to look for exactly the same values in the database.
            If None, will use every key in `data`.

        raise_if_found: bool

        Returns
        -------
        eid: int
            Id of the object inserted or the one found with same `unique_fields`.

        Raises
        ------
        MoreThanOneItemError
            Raise even with `raise_with_found` == False if it finds more than one item
            with the same values as the sample.

        NotUniqueItemError
            If `raise_if_found` is True and an item with the same `unique_fields`
            values from `data` is found in `table`.


def search_unique(self, table_name, sample, unique_fields=None):

return search_unique(table=self.table(table_name),<EOL>sample=sample,<EOL>unique_fields=unique_fields)<EOL>

Search in `table` an item with the value of the `unique_fields` in the `data` sample.
        Check if the the obtained result is unique. If nothing is found will return an empty list,
        if there is more than one item found, will raise an IndexError.

        Parameters
        ----------
        table_name: str

        sample: dict
            Sample data

        unique_fields: list of str
            Name of fields (keys) from `data` which are going to be used to build
            a sample to look for exactly the same values in the database.
            If None, will use every key in `data`.

        Returns
        -------
        eid: int
            Id of the object found with same `unique_fields`.
            None if none is found.

        Raises
        ------
        MoreThanOneItemError
            If more than one example is found.


def search_sample(self, table_name, sample):

return search_sample(table=self.table(table_name),<EOL>sample=sample)<EOL>

Search for items in `table` that have the same field sub-set values as in `sample`.

        Parameters
        ----------
        table_name: str

        sample: dict
            Sample data

        Returns
        -------
        search_result: list of dict
            List of the items found. The list is empty if no item is found.


def is_unique(self, table_name, sample, unique_fields=None):

try:<EOL><INDENT>eid = find_unique(self.table(table_name),<EOL>sample=sample,<EOL>unique_fields=unique_fields)<EOL><DEDENT>except:<EOL><INDENT>return False<EOL><DEDENT>else:<EOL><INDENT>return eid is not None<EOL><DEDENT>

Return True if an item with the value of `unique_fields`
        from `data` is unique in the table with `table_name`.
        False if no sample is found or more than one is found.

        See function `find_unique` for more details.

        Parameters
        ----------
        table_name: str

        sample: dict
            Sample data for query

        unique_fields: str or list of str

        Returns
        -------
        is_unique: bool


def update_unique(self, table_name, fields, data, cond=None, unique_fields=None,<EOL>*, raise_if_not_found=False):

eid = find_unique(self.table(table_name), data, unique_fields)<EOL>if eid is None:<EOL><INDENT>if raise_if_not_found:<EOL><INDENT>msg  = '<STR_LIT>'.format(table_name, data)<EOL>if cond is not None:<EOL><INDENT>msg += '<STR_LIT>'.format(cond)<EOL><DEDENT>raise IndexError(msg)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>self.table(table_name).update(_to_string(fields), cond=cond, eids=[eid])<EOL><DEDENT>return eid<EOL>

Update the unique matching element to have a given set of fields.

        Parameters
        ----------
        table_name: str

        fields: dict or function[dict -> None]
            new data/values to insert into the unique element
            or a method that will update the elements.

        data: dict
            Sample data for query

        cond: tinydb.Query
            which elements to update

        unique_fields: list of str

        raise_if_not_found: bool
            Will raise an exception if the element is not found for update.

        Returns
        -------
        eid: int
            The eid of the updated element if found, None otherwise.


return len(list(search_sample(table=self.table(table_name),<EOL>sample=sample)))<EOL>

Return the number of items that match the `sample` field values
        in table `table_name`.
        Check function search_sample for more details.


install_deps = []<EOL>try:<EOL><INDENT>for fpath in args:<EOL><INDENT>install_deps.extend([str(d.req or d.url) for d in parse_requirements(fpath)])<EOL><DEDENT><DEDENT>except:<EOL><INDENT>print('<STR_LIT>'.format(fpath))<EOL><DEDENT>return [dep for dep in install_deps if dep != '<STR_LIT:None>']<EOL>

Parse all requirements files given and return a list of the dependencies


if regex is None:<EOL><INDENT>regex = '<STR_LIT>'<EOL><DEDENT>files = glob(os.path.join(base_directory, regex))<EOL>for path, dirlist, filelist in os.walk(base_directory):<EOL><INDENT>for ignored in IGNORE:<EOL><INDENT>try:<EOL><INDENT>dirlist.remove(ignored)<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>for dir_name in dirlist:<EOL><INDENT>files.extend(glob(os.path.join(path, dir_name, regex)))<EOL><DEDENT><DEDENT>return files<EOL>

Uses glob to find all files that match the regex in base_directory.

    @param base_directory: string

    @param regex: string

    @return: set


@baker.command(default=True,<EOL>shortopts={'<STR_LIT>': '<STR_LIT:c>',<EOL>'<STR_LIT>': '<STR_LIT:d>',<EOL>'<STR_LIT>': '<STR_LIT:s>',<EOL>'<STR_LIT>': '<STR_LIT:o>'})<EOL>def copy(configfile='<STR_LIT>', destpath='<STR_LIT>', overwrite=False, sub_node='<STR_LIT>'):

log.info('<STR_LIT>'.format(os.path.basename(__file__),<EOL>whoami(),<EOL>locals()))<EOL>assert(os.path.isfile(configfile))<EOL>if os.path.exists(destpath):<EOL><INDENT>if os.listdir(destpath):<EOL><INDENT>raise FolderAlreadyExists('<STR_LIT>'<EOL>'<STR_LIT>'.format(destpath))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>log.info('<STR_LIT>'.format(destpath))<EOL>path(destpath).makedirs_p()<EOL><DEDENT>from boyle.files.file_tree_map import FileTreeMap<EOL>file_map = FileTreeMap()<EOL>try:<EOL><INDENT>file_map.from_config_file(configfile)<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise FileTreeMapError(str(e))<EOL><DEDENT>if sub_node:<EOL><INDENT>sub_map = file_map.get_node(sub_node)<EOL>if not sub_map:<EOL><INDENT>raise FileTreeMapError('<STR_LIT>'<EOL>'<STR_LIT>'.format(sub_node))<EOL><DEDENT>file_map._filetree = {}<EOL>file_map._filetree[sub_node] = sub_map<EOL><DEDENT>try:<EOL><INDENT>file_map.copy_to(destpath, overwrite=overwrite)<EOL><DEDENT>except Exception as e:<EOL><INDENT>raise FileTreeMapError(str(e))<EOL><DEDENT>

Copies the files in the built file tree map
    to despath.

    :param configfile: string
     Path to the FileTreeMap config file

    :param destpath: string
     Path to the files destination

    :param overwrite: bool
     Overwrite files if they already exist.

    :param sub_node: string
     Tree map configuration sub path.
     Will copy only the contents within this sub-node


<EOL>try:<EOL><INDENT>nun = np.array(None).astype(self.dtype)<EOL>return np.array(self.reflst)[self == nun]<EOL><DEDENT>except:<EOL><INDENT>nun = None<EOL>return np.array(self.reflst)[self is None]<EOL><DEDENT>

Returns
-------
ndarray
Array of references in self.reflst whose self id is None.


def _print_general_vs_table(self, idset1, idset2):

ref1name = '<STR_LIT>'<EOL>set1_hasref = isinstance(idset1, idset_with_reference)<EOL>if set1_hasref:<EOL><INDENT>ref1arr = np.array(idset1.reflst)<EOL>ref1name = idset1.refname<EOL><DEDENT>ref2name = ref1name<EOL>set2_hasref = isinstance(idset2, idset_with_reference)<EOL>if set2_hasref:<EOL><INDENT>ref2arr = np.array(idset2.reflst)<EOL>ref2name = idset2.refname<EOL><DEDENT>else:<EOL><INDENT>ref2name = ref1name<EOL><DEDENT>hdr11 = '<STR_LIT>'.format(idset1.name, idset2.name)<EOL>hdr12 = '<STR_LIT>'.format(idset1.name, idset2.name, ref2name)<EOL>hdr13 = '<STR_LIT>'.format(idset1.name, idset2.name)<EOL>hdr14 = '<STR_LIT>'.format(idset1.name, idset2.name, ref1name)<EOL>table = [[hdr11, hdr12, hdr13, hdr14]]<EOL>set1 = set(idset1)<EOL>set2 = set(idset2)<EOL>row11 = list(set1 - set2)<EOL>if set1_hasref:<EOL><INDENT>row12 = [ref1arr[np.where(idset1 == nom)][<NUM_LIT:0>] for nom in row11]<EOL><DEDENT>else:<EOL><INDENT>row12 = ['<STR_LIT>' for _ in row11]<EOL><DEDENT>row13 = list(set2 - set1)<EOL>if set2_hasref:<EOL><INDENT>row14 = [ref2arr[np.where(idset2 == nom)][<NUM_LIT:0>] for nom in row13]<EOL><DEDENT>else:<EOL><INDENT>row14 = ['<STR_LIT>' for _ in row13]<EOL><DEDENT>tablst = self._tabulate_4_lists(row11, row12, row13, row14)<EOL>table.extend(tablst)<EOL>if len(table) > <NUM_LIT:1>:<EOL><INDENT>print(tabulate(table, headers='<STR_LIT>'))<EOL>print('<STR_LIT:\n>')<EOL><DEDENT>


def _print_foreign_repetition_table(self, idset1, idset2):

assert(isinstance(idset1, idset_with_reference))<EOL>assert(isinstance(idset2, idset))<EOL>reps = idset2.get_repetitions()<EOL>if len(reps) < <NUM_LIT:1>:<EOL><INDENT>return<EOL><DEDENT>refs = np.array(idset1.reflst)<EOL>table = [['<STR_LIT>'.format(idset1.name,<EOL>idset1.refname,<EOL>idset2.name),<EOL>'<STR_LIT>']]<EOL>for rep in reps:<EOL><INDENT>if np.any(idset1 == rep):<EOL><INDENT>matches = refs[np.where(idset1 == rep)]<EOL>myrep = rep<EOL>for m in matches:<EOL><INDENT>table.append([myrep, m])<EOL>myrep = '<STR_LIT>'<EOL><DEDENT><DEDENT><DEDENT>print(tabulate(table, headers='<STR_LIT>'))<EOL>print('<STR_LIT:\n>')<EOL>


def print_compare_idsets_one_ref(self, idset1_name, idset2_name):

try:<EOL><INDENT>idset1 = self[idset1_name]<EOL>idset2 = self[idset2_name]<EOL><DEDENT>except KeyError as ke:<EOL><INDENT>log.error('<STR_LIT>'.format(idset1_name,<EOL>idset2_name))<EOL>import sys, pdb<EOL>pdb.post_mortem(sys.exc_info()[<NUM_LIT:2>])<EOL>raise<EOL><DEDENT>assert(isinstance(idset1, idset_with_reference))<EOL>assert(isinstance(idset2, idset))<EOL>self._print_general_vs_table(idset1, idset2)<EOL>self._print_foreign_repetition_table(idset1, idset2)<EOL>

idset1_name: string
key of an idset_with_reference

idset2_name: string
key of an idset


def print_compare_idsets_two_refs(self, idset1_name, idset2_name):

try:<EOL><INDENT>idset1 = self[idset1_name]<EOL>idset2 = self[idset2_name]<EOL><DEDENT>except KeyError as ke:<EOL><INDENT>log.error('<STR_LIT>'.format(idset1_name,<EOL>idset2_name))<EOL>import sys, pdb<EOL>pdb.post_mortem(sys.exc_info()[<NUM_LIT:2>])<EOL>raise<EOL><DEDENT>assert(isinstance(idset1, idset_with_reference))<EOL>assert(isinstance(idset2, idset_with_reference))<EOL>self._print_general_vs_table(idset1, idset2)<EOL>self._print_foreign_repetition_table(idset1, idset2)<EOL>self._print_foreign_repetition_table(idset2, idset1)<EOL>


@baker.command(name='<STR_LIT>',<EOL>params={"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": "<STR_LIT>",<EOL>"<STR_LIT>": """<STR_LIT>""",<EOL>"<STR_LIT>": """<STR_LIT>"""},<EOL>shortopts={'<STR_LIT>': '<STR_LIT:i>', '<STR_LIT>': '<STR_LIT:o>', <EOL>'<STR_LIT>': '<STR_LIT:m>', '<STR_LIT>': '<STR_LIT:t>'})<EOL>def convert_sav(inputfile, outputfile=None, method='<STR_LIT>', otype='<STR_LIT>'):

assert(os.path.isfile(inputfile))<EOL>assert(method=='<STR_LIT>' or method=='<STR_LIT>')<EOL>if method == '<STR_LIT>':<EOL><INDENT>df = sav_to_pandas_rpy2(inputfile)<EOL><DEDENT>elif method == '<STR_LIT>':<EOL><INDENT>df = sav_to_pandas_savreader(inputfile)<EOL><DEDENT>otype_exts = {'<STR_LIT>': '<STR_LIT>', <EOL>'<STR_LIT>': '<STR_LIT>', <EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT>': '<STR_LIT>',<EOL>'<STR_LIT:html>': '<STR_LIT>'}<EOL>if outputfile is None:<EOL><INDENT>outputfile = inputfile.replace(path(inputfile).ext, '<STR_LIT>')<EOL><DEDENT>outputfile = add_extension_if_needed(outputfile, otype_exts[otype])<EOL>if otype == '<STR_LIT>':<EOL><INDENT>df.to_csv(outputfile)<EOL><DEDENT>elif otype == '<STR_LIT>':<EOL><INDENT>df.to_hdf(outputfile, os.path.basename(outputfile))<EOL><DEDENT>elif otype == '<STR_LIT>':<EOL><INDENT>df.to_stata(outputfile)<EOL><DEDENT>elif otype == '<STR_LIT>':<EOL><INDENT>df.to_json(outputfile)<EOL><DEDENT>elif otype == '<STR_LIT>':<EOL><INDENT>df.to_pickle(outputfile)<EOL><DEDENT>elif otype == '<STR_LIT>':<EOL><INDENT>df.to_excel(outputfile)<EOL><DEDENT>elif otype == '<STR_LIT:html>':<EOL><INDENT>df.to_html(outputfile)<EOL><DEDENT>else:<EOL><INDENT>df.to_csv(outputfile)<EOL><DEDENT>

Transforms the input .sav SPSS file into other format.
    If you don't specify an outputfile, it will use the
    inputfile and change its extension to .csv


pathSplit = os.environ['<STR_LIT>'].split('<STR_LIT::>')<EOL>if '<STR_LIT:.>' not in pathSplit:<EOL><INDENT>pathSplit = ['<STR_LIT:.>'] + pathSplit<EOL>os.environ['<STR_LIT>'] = '<STR_LIT::>'.join(pathSplit)<EOL><DEDENT>result = '<STR_LIT>'<EOL>success = False<EOL>for path in pathSplit:<EOL><INDENT>if path.endswith('<STR_LIT:/>'):<EOL><INDENT>path = path[:-<NUM_LIT:1>]<EOL><DEDENT>guess = path + '<STR_LIT>'<EOL>if os.path.exists(guess):<EOL><INDENT>success = True<EOL>result = guess<EOL>break<EOL><DEDENT><DEDENT>return {<EOL>'<STR_LIT:path>'    : result,<EOL>"<STR_LIT:success>" : success <EOL>}<EOL>

findGoodTests - Tries to find GoodTests.py

@return <dict> {
    'path' <str> -> Path to GoodTests.py (for execution)
    'success' <bool> -> True/False if we successfully found GoodTests.py
}


try:<EOL><INDENT>b'<STR_LIT>'.decode(encoding)<EOL><DEDENT>except:<EOL><INDENT>raise ValueError('<STR_LIT>' %(str(encoding), ))<EOL><DEDENT>global defaultIREncoding<EOL>defaultIREncoding = encoding<EOL>

setDefaultIREncoding - Sets the default encoding used by IndexedRedis.
  This will be the default encoding used for field data. You can override this on a
  per-field basis by using an IRField (such as IRUnicodeField or IRRawField)

@param encoding - An encoding (like utf-8)


global defaultIREncoding<EOL>return defaultIREncoding<EOL>

getDefaultIREncoding - Get the default encoding that IndexedRedis will use for all field data.
  You can override this on a per-field basis by using an IRField (such as IRUnicodeField or IRRawField)

  @return <str> - Default encoding string


return issubclass(x.__class__, encoded_str_type)<EOL>

isEncodedString - Check if a given string is "encoded" with a codepage.

  Note this means UNICODE, not BYTES, even though python uses "decode" to apply an encoding and "encode" to get the raw bytes..


self.valueType = None<EOL>self.defaultValue = '<STR_LIT>'<EOL>

__init__ - Create an IRRawField. Only takes a name

@param name <str> - Field name

This field type does not support indexing.


def __init__(self, name='<STR_LIT>', defaultValue=irNull, encoding=None):

self.valueType = None<EOL>self.encoding = encoding<EOL>self.defaultValue = defaultValue<EOL>

__init__ - Create an IRBase64Field object.

@param name <str> - Field name

@param defaultValue <any> (Default irNull) - Default value of field

@param encoding <None/str> (default None) - An explicit encoding to use when converting to bytes. If None, the global defaultIREncoding will be used.

An IRBytesField is indexable and the index is forced to be hashed


return IrNullBaseType.__new__(self, '<STR_LIT>')<EOL>


def __init__(self, name='<STR_LIT>', compressMode=COMPRESS_MODE_ZLIB, defaultValue=irNull):

self.valueType = None<EOL>self.defaultValue = defaultValue<EOL>if compressMode == COMPRESS_MODE_ZLIB or compressMode in _COMPRESS_MODE_ALIASES_ZLIB:<EOL><INDENT>self.compressMode = COMPRESS_MODE_ZLIB<EOL>self.header = b'<STR_LIT>'<EOL>self.extraCompressArgs = (<NUM_LIT:9>, )<EOL><DEDENT>elif compressMode == COMPRESS_MODE_BZ2 or compressMode in _COMPRESS_MODE_ALIASES_BZ2:<EOL><INDENT>self.compressMode = COMPRESS_MODE_BZ2<EOL>self.header = b'<STR_LIT>'<EOL>self.extraCompressArgs = (<NUM_LIT:9>, )<EOL><DEDENT>elif compressMode == COMPRESS_MODE_LZMA or compressMode in _COMPRESS_MODE_ALIASES_LZMA:<EOL><INDENT>self.compressMode = COMPRESS_MODE_LZMA<EOL>self.header = b'<STR_LIT>'<EOL>self.extraCompressArgs = tuple()<EOL>self.getCompressMod() <EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>' %(str(compressMode), name))<EOL><DEDENT>

__init__ - Create this object

@param name <str> - Field name
@param compressMode <str>, default "zlib". Determines the compression module to use
  for this field. See COMPRESS_MODE_* variables in this module.

  Supported values as of 5.0.0 are:

     "zlib" / "gz" / "gzip" - zlib compression

     "bz2"  / "bzip2"       - bzip2 compression

     "lzma" / "xz"          - LZMA compression.
       NOTE: This is provided in python3 by default, but in python2 you will need an external module.
        IndexedRedis will automatically detect if "backports.lzma" or "lzmaffi" are installed, and use them
        if the core "lzma" module is not available.

@param defaultValue - The default value for this field

An IRCompressedField is indexable, and forces the index to be hashed.


if self.compressMode == COMPRESS_MODE_ZLIB:<EOL><INDENT>return zlib<EOL><DEDENT>if self.compressMode == COMPRESS_MODE_BZ2:<EOL><INDENT>return bz2<EOL><DEDENT>if self.compressMode == COMPRESS_MODE_LZMA:<EOL><INDENT>global _lzmaMod<EOL>if _lzmaMod is not None:<EOL><INDENT>return _lzmaMod<EOL><DEDENT>try:<EOL><INDENT>import lzma<EOL>_lzmaMod = lzma<EOL>return _lzmaMod<EOL><DEDENT>except:<EOL><INDENT>try:<EOL><INDENT>from backports import lzma<EOL>_lzmaMod = lzma<EOL>return _lzmaMod<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>try:<EOL><INDENT>import lzmaffi as lzma<EOL>_lzmaMod = lzma<EOL>return _lzmaMod<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>raise ImportError("<STR_LIT>")<EOL><DEDENT><DEDENT>

getCompressMod - Return the module used for compression on this field

@return <module> - The module for compression


def __init__(self, pk=None, foreignModel=None, obj=None):

self.pk = pk<EOL>self.obj = obj<EOL>if foreignModel is not None:<EOL><INDENT>if issubclass(foreignModel.__class__, weakref.ReferenceType):<EOL><INDENT>foreignModel = foreignModel()<EOL><DEDENT>self._foreignModel = weakref.ref(foreignModel)<EOL><DEDENT>else:<EOL><INDENT>self._foreignModel = None<EOL><DEDENT>

__init__ - Create a ForeignLinkData object

@param pk <int> - The primary key of the foreign object
@param obj <None/IndexedRedisModel> - The resolved object, or None if not yet resolved


return self._foreignModel()<EOL>

foreignModel - Resolve and return the weakref to the associated foreign model


if self.obj is None:<EOL><INDENT>if not self.pk:<EOL><INDENT>return None<EOL><DEDENT>self.obj = self.foreignModel.objects.get(self.pk)<EOL><DEDENT>return self.obj<EOL>

getObj - Fetch (if not fetched) and return the obj associated with this data.


return [ self.getObj() ]<EOL>

getObjs - Fetch (if not fetched) and return the obj associated with this data.

        Output is iterable.


if not self.pk and self.obj:<EOL><INDENT>if self.obj._id:<EOL><INDENT>self.pk = self.obj._id<EOL><DEDENT><DEDENT>return self.pk<EOL>

getPk - Resolve any absent pk's off the obj's (like if an obj has been saved), and return the pk.


return not bool(self.obj is None)<EOL>

isFetched - Check if the associated obj has been fetched or not.


if not self.obj:<EOL><INDENT>return False<EOL><DEDENT>return self.obj.hasUnsavedChanges(cascadeObjects=True)<EOL>

objHasUnsavedChanges - Check if any object has unsaved changes, cascading.


ForeignLinkData.__init__(self, pk, foreignModel, obj)<EOL>pk = self.pk<EOL>obj = self.obj<EOL>if pk and not obj:<EOL><INDENT>self.obj = [None for i in range(len(pk))]<EOL><DEDENT>elif obj and not pk:<EOL><INDENT>self.pk = []<EOL>for thisObj in obj:<EOL><INDENT>if thisObj._id:<EOL><INDENT>self.pk.append(thisObj._id)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT><DEDENT><DEDENT>elif len(obj) != len(pk):<EOL><INDENT>if len(pk) > len(obj):<EOL><INDENT>self.obj += [None for i in range( len(pk) - len(obj) ) ]<EOL><DEDENT>else:<EOL><INDENT>for thisObj in obj[len(pk):]:<EOL><INDENT>if thisObj._id:<EOL><INDENT>self.pk.append(thisObj._id)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT><DEDENT><DEDENT><DEDENT>

__init__ - Create a ForeignLinkMultiData

@see ForeignLinkData


if not self.pk or None in self.pk:<EOL><INDENT>for i in range( len(self.pk) ):<EOL><INDENT>if self.pk[i]:<EOL><INDENT>continue<EOL><DEDENT>if self.obj[i] and self.obj[i]._id:<EOL><INDENT>self.pk[i] = self.obj[i]._id<EOL><DEDENT><DEDENT><DEDENT>return self.pk<EOL>


if self.obj:<EOL><INDENT>needPks = [ (i, self.pk[i]) for i in range(len(self.obj)) if self.obj[i] is None]<EOL>if not needPks:<EOL><INDENT>return self.obj<EOL><DEDENT>fetched = list(self.foreignModel.objects.getMultiple([needPk[<NUM_LIT:1>] for needPk in needPks]))<EOL>i = <NUM_LIT:0><EOL>for objIdx, pk in needPks:<EOL><INDENT>self.obj[objIdx] = fetched[i]<EOL>i += <NUM_LIT:1><EOL><DEDENT><DEDENT>return self.obj<EOL>

getObj - @see ForeignLinkData.getObj

        Except this always returns a list


return self.getObj()<EOL>


if not self.obj:<EOL><INDENT>return False<EOL><DEDENT>if not self.pk or None in self.obj:<EOL><INDENT>return False<EOL><DEDENT>return not bool(self.obj is None)<EOL>

isFetched - @see ForeignLinkData.isFetched


if not self.obj:<EOL><INDENT>return False<EOL><DEDENT>for thisObj in self.obj:<EOL><INDENT>if not thisObj:<EOL><INDENT>continue<EOL><DEDENT>if thisObj.hasUnsavedChanges(cascadeObjects=True):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>return False<EOL>

objHasUnsavedChanges - @see ForeignLinkData.objHasUnsavedChanges

True if ANY object has unsaved changes.


def __init__(self, name='<STR_LIT>', foreignModel=None):

IRField.__init__(self, name, valueType=int, defaultValue=irNull)<EOL>if foreignModel:<EOL><INDENT>if not isinstance(foreignModel, type):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>if not hasattr(foreignModel, '<STR_LIT>'):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT><DEDENT>self._foreignModel = weakref.ref(foreignModel)<EOL>

__init__ - Create an IRForeignLinkField. Only takes a name

@param name <str> - Field name

This field type does not support indexing.


return self._foreignModel()<EOL>

foreignModel - Resolve and return the weakref to the associated Foreign Model


return False<EOL>

isMulti - Returns True if this is a MultiLink object (expects lists), otherwise False (expects object)

@return <bool>


return True<EOL>


def __init__(self, name='<STR_LIT>', defaultValue=irNull):

self.valueType = None<EOL>self.defaultValue = defaultValue<EOL>

__init__ - Create an IRPickleField

@param name <str> - Field name

@param defaultValue - The default value of this field

Because even with the same format, python2 and python3 can output different pickle strings for the same object,
  as well as different host configurations may lead to different output, this field type is not indexable.


def __init__(self, name='<STR_LIT>', decimalPlaces=<NUM_LIT:5>, defaultValue=irNull):

self.decimalPlaces = decimalPlaces<EOL>if isinstance(defaultValue, int):<EOL><INDENT>defaultValue = float(defaultValue)<EOL><DEDENT>elif isinstance(defaultValue, float):<EOL><INDENT>defaultValue = round(defaultValue, decimalPlaces)<EOL><DEDENT>self.defaultValue = defaultValue<EOL>

__init__ - Create this object.

@param name <str> - Field name (or blank if used in an IRFieldChain)

@param decimalPlaces <int> - The number of decimal places to use (precision). Values will be rounded to this many places, and always have
  this many digits after the decimal point.

@param defaultValue - The default value for this field

An IRFixedPointField is indexable, and has no option to hash the index.


def __init__(self, name='<STR_LIT>', valueType=str, defaultValue=irNull, hashIndex=False):

self.defaultValue = defaultValue<EOL>self.hashIndex = hashIndex<EOL>if valueType in (str, unicode):<EOL><INDENT>valueType = str<EOL>self._fromStorage = self._convertStr<EOL>self._fromInput = self._convertStr<EOL>self._toStorage = self._convertStr<EOL><DEDENT>elif bytes != str and valueType == bytes:<EOL><INDENT>valueType = bytes<EOL>self._fromStorage = self._convertBytes<EOL>self._fromInput = self._convertBytes<EOL>self._toStorage = self._convertBytes<EOL>self.CAN_INDEX = False<EOL><DEDENT>elif valueType in (None, type(None)):<EOL><INDENT>self._fromStorage = self._noConvert<EOL>self._fromInput = self._noConvert<EOL>self._toStorage = self._noConvert<EOL>self.CAN_INDEX = False<EOL><DEDENT>elif valueType in (dict, list, tuple):<EOL>ecatedMessage('<STR_LIT>' %(repr(name), valueType.__name__, repr(name)), printStack=True)<EOL><INDENT>valueType = IRJsonValue<EOL>self.CAN_INDEX = IRJsonValue.CAN_INDEX<EOL><DEDENT>elif valueType == datetime:<EOL>ecatedMessage('<STR_LIT>' %(repr(name), repr(name)), printStack=True)<EOL><INDENT>valueType = IRDatetimeValue<EOL>self.CAN_INDEX = IRDatetimeValue.CAN_INDEX<EOL><DEDENT>else:<EOL><INDENT>if not isinstance(valueType, type):<EOL><INDENT>raise TypeError('<STR_LIT>' %(repr(valueType,)))<EOL><DEDENT>if valueType == bool:<EOL><INDENT>self._fromStorage = self._convertBool<EOL>self._fromInput = self._convertBool<EOL><DEDENT>elif isinstance(valueType, (set, frozenset, )):<EOL><INDENT>raise TypeError('<STR_LIT>')<EOL><DEDENT><DEDENT>self.valueType = valueType<EOL>if valueType in (str, unicode, int, bool):<EOL><INDENT>self.CAN_INDEX = True<EOL><DEDENT>elif hasattr(valueType, '<STR_LIT>'):<EOL><INDENT>self.CAN_INDEX = valueType.CAN_INDEX<EOL><DEDENT>

__init__ - Create an IRField. Use this directly in the FIELDS array for advanced functionality on a field.

@param name <str> - The name of this field

@param valueType <type> - The type that will be used for this field. Default str/unicode (and bytes on python2)
        act the same as non-IRField FIELDS entries (just plain string), i.e. they are encoded to unicode to and from Redis.

        If you pass in None, then no decoding will take place (so whatever you provide goes in, and bytes come out of Redis).
        This is similar to IRFieldRaw

        On python3, if you pass bytes, than the field will be left as bytes.
        To be both python2 and python3 compatible, however, you can use IRBytesField

        If bool is used, then "1" and "true" are True, "0" and "false" are False, any other value is an exception.

        You can also pass an advanced type (see IndexedRedis.fields.FieldValueTypes) like datetime and json.

        All types other than string/unicode/bytes/None will be assigned 'irNull' if they were not provided a value.
        @see irNull - Equals only irNull (or other IRNullType instances). You can use this to check if an integer is defined versus 0, for example.

        While this class is create for primitive types (like int's and datetimes), more complex types extend IRField (such as pickle, compressed, or unicode with a specific encoding).

@param defaultValue <any> (default irNull) - The value assigned to this field as a "default", i.e. when no value has yet been set. Generally, it makes sense to keep this as irNull, but you may want a different default.

@param hashIndex <bool> (default False) - If true, the md5 hash of the value will be used for indexing and filtering. This may be useful for very long fields.

An IRField may be indexable (depending on the type), and has the option to hash the index

NOTE: If you are extending IRField, you should probably not call this __init__ function. So long as you implement your own "convert", any fields used are set on a class-level.


if value == irNull or None:<EOL><INDENT>return IR_NULL_STR<EOL><DEDENT>return self._toStorage(value)<EOL>

toStorage - Convert the value to a string representation for storage.

  The default implementation will work here for basic types.

@param value - The value of the item to convert
@return A string value suitable for storing.


return to_unicode(value)<EOL>

_toStorage - Convert the value to a string for storage.

The default implementation works for most valueTypes within IRField, override this for extending types.

You don't need to handle null

@param value - Value of item to convert

@return - A string value suitable for storing


if value in IR_NULL_STRINGS:<EOL><INDENT>return irNull<EOL><DEDENT>return self._fromStorage(value)<EOL>

fromStorage - Convert the value from storage to the value type.

@param value - Value to convert

@return - The converted value


return self.valueType(value)<EOL>

_fromStorage - Convert the value from storage to the value type.

  This default impl works fine for most value types, should be implemented by extending types.

  @param value - Value to convert

  @return - Converted value


if value == irNull:<EOL><INDENT>return irNull<EOL><DEDENT>return self._fromInput(value)<EOL>

fromInput - Convert the value from input (like assigning this through constructor or as an item assignment on the object

@param value - Value to convert

@return - Converted value


return self.valueType(value)<EOL>

_fromInput - Convert the value from input. Implement this in extending types.

@param value - Value to convert

@return converted value


if self._isIrNull(value):<EOL><INDENT>ret = IR_NULL_STR<EOL><DEDENT>else:<EOL><INDENT>ret = self._toIndex(value)<EOL><DEDENT>if self.isIndexHashed is False:<EOL><INDENT>return ret<EOL><DEDENT>return md5(tobytes(ret)).hexdigest()<EOL>

toIndex - An optional method which will return the value prepped for index.

By default, "toStorage" will be called. If you provide "hashIndex=True" on the constructor,
the field will be md5summed for indexing purposes. This is useful for large strings, etc.


return self.defaultValue<EOL>

getDefaultValue - Gets the default value associated with this field.

  This is the value used when no value has been explicitly set.

  @return - The default value


return bool(self.hashIndex)<EOL>

isIndexHashed - Returns if the index value should be hashed

@return <bool> - True if this field should be hashed before indexing / filtering


return str(self)<EOL>

name - Property, return this field's name

@return <str> - Field name


return bool(value in (b'<STR_LIT>', '<STR_LIT>', irNull, None) or value in IR_NULL_STRINGS )<EOL>

_isNullValue - Tests value if it should be represented by irNull.

convert and toStorage should test if value is null and return null (for most types)


ret = []<EOL>if getattr(self, '<STR_LIT>', None) is not None:<EOL><INDENT>ret.append('<STR_LIT>' %(self.valueType.__name__, ))<EOL><DEDENT>if hasattr(self, '<STR_LIT>'):<EOL><INDENT>ret.append('<STR_LIT>' %(self.hashIndex, ))<EOL><DEDENT>return ret<EOL>

_getReprProperties - Get the properties of this field to display in repr().

        These should be in the form of $propertyName=$propertyRepr

        The default IRField implementation handles just the "hashIndex" property.

        defaultValue is part of "__repr__" impl. You should just extend this method
        with your object's properties instead of rewriting repr.


ret = [ self.__class__.__name__, '<STR_LIT>', '<STR_LIT>' %(str(self), ) ]<EOL>reprProperties = self._getReprProperties()<EOL>defaultValue = self.getDefaultValue()<EOL>if defaultValue == irNull:<EOL><INDENT>reprProperties.append('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>reprProperties.append('<STR_LIT>' %(repr(defaultValue), ))<EOL><DEDENT>ret.append('<STR_LIT:U+002CU+0020>')<EOL>ret.append('<STR_LIT:U+002CU+0020>'.join(reprProperties))<EOL>ret.append('<STR_LIT>')<EOL>return '<STR_LIT>'.join(ret)<EOL>

__repr__ - Return an object-representation string of this field instance.

You should NOT need to extend this on your IRField, instead just implement _getReprProperties

  to return your type's specific properties associated with this instance.

  @see _getReprProperties


return self.__class__(name=self.name, valueType=self.valueType, defaultValue=self.defaultValue, hashIndex=self.hashIndex)<EOL>

copy - Create a copy of this IRField.

  Each subclass should implement this, as you'll need to pass in the args to constructor.

@return <IRField (or subclass)> - Another IRField that has all the same values as this one.


IRField.__init__(self, name=name, valueType=str, defaultValue='<STR_LIT>')<EOL>

__init__ - Create an IRClassicField.
  This field behaves as a plain string entry in FIELDS did prior to 5.0.0.

  The default value is empty string, and it stores strings using defaultIREncoding.

  Consider changing to an IRField or one of the other many types.

  @param name <str> - Field name


def __init__(self, name='<STR_LIT>', encoding=None, defaultValue=irNull):

self.valueType = None<EOL>self.encoding = encoding<EOL>self.defaultValue = defaultValue<EOL>

__init__ - Create an IRUnicodeField

@param name <str> - The field name

@param encoding <None/str> - A specific encoding to use. If None, defaultIREncoding will be used.

@param defaultValue - The default value for this field

This field type is indeaxble, and the index is forced to be hashed.


if not self.encoding:<EOL><INDENT>return getDefaultIREncoding()<EOL><DEDENT>return self.encoding<EOL>

getEncoding - Get the encoding codec associated with this field.

        If you provided None, this will return the defaultIREncoding

@return <str> - Encoding


if type(value) == bytes:<EOL><INDENT>return value<EOL><DEDENT>return value.encode(self.getEncoding())<EOL>

toBytes - Convert a value to bytes using the encoding specified on this field

@param value <str> - The field to convert to bytes

@return <bytes> - The object encoded using the codec specified on this field.

NOTE: This method may go away.


def __init__(self, name, chainedFields, defaultValue=irNull, hashIndex=False):

if not name:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>self.chainedFields = []<EOL>if not chainedFields:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>for field in chainedFields:<EOL><INDENT>if type(field) == type:<EOL><INDENT>field = field()<EOL><DEDENT>if str(field) != '<STR_LIT>':<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>if not issubclass(field.__class__, IRField):<EOL><INDENT>raise ValueError("<STR_LIT>" %(str(type(field)), repr(field)))<EOL><DEDENT>self.chainedFields.append(field)<EOL><DEDENT>self.defaultValue = defaultValue<EOL>(canIndex, forceHashIndex) = self._checkCanIndex()<EOL>self.CAN_INDEX = canIndex<EOL>if hashIndex is False:<EOL><INDENT>hashIndex = forceHashIndex<EOL><DEDENT>self.hashIndex = hashIndex<EOL>

__init__ - Create an IRFieldChain object.

  These chain together the operations from multiple fields.

  toStorage is applied left-to-right,
  fromInput and fromStorage is applied right-to-left.

  The output of one field is the input of the next.

   An IRFieldChain is indexable so long as ALL of its contained fields are indexable.
   An IRFieldChain is forced to be a hashed index if the rightmost field forces it (as some types do),
     otherwise hashIndex will determine if it is hashed.

@see IRField.__init__


for chainedField in self.chainedFields:<EOL><INDENT>value = chainedField.toStorage(value)<EOL><DEDENT>return value<EOL>

_toStorage - Convert the value to a string representation for storage.

@param value - The value of the item to convert
@return A string value suitable for storing.


for chainedField in reversed(self.chainedFields):<EOL><INDENT>value = chainedField._fromStorage(value)<EOL><DEDENT>return value<EOL>

_fromStorage - Convert the value from storage (string) to the value type.

@return - The converted value, or "irNull" if no value was defined (and field type is not default/string)


<EOL>if not self.chainedFields:<EOL><INDENT>return (False, False)<EOL><DEDENT>for chainedField in self.chainedFields:<EOL><INDENT>if chainedField.CAN_INDEX is False:<EOL><INDENT>return (False, False)<EOL><DEDENT><DEDENT>return (True, self.chainedFields[-<NUM_LIT:1>].hashIndex)<EOL>

_checkCanIndex - Check if we CAN index (if all fields are indexable).
        Also checks the right-most field for "hashIndex" - if it needs to hash we will hash.


self.valueType = None<EOL>self.defaultValue = defaultValue<EOL>self.encoding = encoding<EOL>

__init__ - Create an IRBytesField object

@param name <str> - Field name

@param defaultValue <any> default irNull - Default value for this field

@param encoding <None/str> - If None, defaultIREncoding will be used when converting to bytes,
  otherwise you can provide an explicit encoding

An IRBytesField is indexable, and the index is forced to be hashed.


if val is None:<EOL><INDENT>QueryableListObjs.__init__(self)<EOL><DEDENT>else:<EOL><INDENT>QueryableListObjs.__init__(self, val)<EOL><DEDENT>self.mdl = mdl<EOL>if not mdl:<EOL><INDENT>self.mdl = self.getModel()<EOL><DEDENT>else:<EOL><INDENT>self.__validate_model(mdl)<EOL><DEDENT>

__init__ - Create this object

@param val - None for empty list, IndexedRedisModel for a one-item list, or a list/tuple or subclass of initial values.
@param mdl - The IndexedRedisModel that this list will contain. Provide this now if you can, otherwise it will be inferred from
  the first item added or present in the list.

@raises ValueError if "mdl" is not an IndexedRedisModel


if not hasattr(mdl, '<STR_LIT>'):<EOL><INDENT>raise ValueError('<STR_LIT>' %(str(mdl.__class__.__name__),))<EOL><DEDENT>

__validate_model - Internal function to check that model is of correct type.

Uses a class variable that has been defined for IndexedRedisModel s for a long time, not the type itself, to prevent circular imports etc.

@param mdl - type to validate


if not self.mdl and len(self) > <NUM_LIT:0>:<EOL><INDENT>mdl = self[<NUM_LIT:0>].__class__<EOL>self.__validate_model(mdl)<EOL>self.mdl = mdl<EOL><DEDENT>return self.mdl<EOL>

getModel - get the IndexedRedisModel associated with this list. If one was not provided in constructor,
  it will be inferred from the first item in the list (if present)

  @return <None/IndexedRedisModel> - None if none could be found, otherwise the IndexedRedisModel type of the items in this list.

@raises ValueError if first item is not the expected type.


if len(self) == <NUM_LIT:0>:<EOL><INDENT>return <NUM_LIT:0><EOL><DEDENT>mdl = self.getModel()<EOL>return mdl.deleter.deleteMultiple(self)<EOL>

delete - Delete all objects in this list.

@return <int> - Number of objects deleted


if len(self) == <NUM_LIT:0>:<EOL><INDENT>return []<EOL><DEDENT>mdl = self.getModel()<EOL>return mdl.saver.save(self)<EOL>


if len(self) == <NUM_LIT:0>:<EOL><INDENT>return []<EOL><DEDENT>ret = []<EOL>for obj in self:<EOL><INDENT>res = None<EOL>try:<EOL><INDENT>res = obj.reload()<EOL><DEDENT>except Exception as e:<EOL><INDENT>res = e<EOL><DEDENT>ret.append(res)<EOL><DEDENT>return ret<EOL>

reload - Reload all objects in this list.
        Updates in-place. To just fetch all these objects again, use "refetch"

@return - List (same order as current objects) of either exception (KeyError) if operation failed,
  or a dict of fields changed -> (old, new)


if len(self) == <NUM_LIT:0>:<EOL><INDENT>return IRQueryableList()<EOL><DEDENT>mdl = self.getModel()<EOL>pks = [item._id for item in self if item._id]<EOL>return mdl.objects.getMultiple(pks)<EOL>

refetch - Fetch a fresh copy of all items in this list.
        Returns a new list. To update in-place, use "reload".

@return IRQueryableList<IndexedRedisModel> - List of fetched items


def setDefaultRedisConnectionParams( connectionParams ):

global _defaultRedisConnectionParams<EOL>_defaultRedisConnectionParams.clear()<EOL>for key, value in connectionParams.items():<EOL><INDENT>_defaultRedisConnectionParams[key] = value<EOL><DEDENT>clearRedisPools()<EOL>

setDefaultRedisConnectionParams - Sets the default parameters used when connecting to Redis.

  This should be the args to redis.Redis in dict (kwargs) form.

  @param connectionParams <dict> - A dict of connection parameters.
    Common keys are:

       host <str> - hostname/ip of Redis server (default '127.0.0.1')
       port <int> - Port number			(default 6379)
       db  <int>  - Redis DB number		(default 0)

   Omitting any of those keys will ensure the default value listed is used.

  This connection info will be used by default for all connections to Redis, unless explicitly set otherwise.
  The common way to override is to define REDIS_CONNECTION_PARAMS on a model, or use AltConnectedModel = MyModel.connectAlt( PARAMS )

  Any omitted fields in these connection overrides will inherit the value from the global default.

  For example, if your global default connection params define host = 'example.com', port=15000, and db=0,
    and then one of your models has

       REDIS_CONNECTION_PARAMS = { 'db' : 1 }

    as an attribute, then that model's connection will inherit host='example.com" and port=15000 but override db and use db=1

    NOTE: Calling this function will clear the connection_pool attribute of all stored managed connections, disconnect all managed connections,
      and close-out the connection pool.
     It may not be safe to call this function while other threads are potentially hitting Redis (not that it would make sense anyway...)

     @see clearRedisPools   for more info


global _defaultRedisConnectionParams<EOL>return copy.copy(_defaultRedisConnectionParams)<EOL>

getDefaultRedisConnectionParams - Gets A COPY OF the default Redis connection params.

@see setDefaultRedisConnectionParams for more info

@return <dict> - copy of default Redis connection parameters


global RedisPools<EOL>global _redisManagedConnectionParams<EOL>for pool in RedisPools.values():<EOL><INDENT>try:<EOL><INDENT>pool.disconnect()<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>for paramsList in _redisManagedConnectionParams.values():<EOL><INDENT>for params in paramsList:<EOL><INDENT>if '<STR_LIT>' in params:<EOL><INDENT>del params['<STR_LIT>']<EOL><DEDENT><DEDENT><DEDENT>RedisPools.clear()<EOL>_redisManagedConnectionParams.clear()<EOL>

clearRedisPools - Disconnect all managed connection pools,
   and clear the connectiobn_pool attribute on all stored managed connection pools.

   A "managed" connection pool is one where REDIS_CONNECTION_PARAMS does not define the "connection_pool" attribute.
   If you define your own pools, IndexedRedis will use them and leave them alone.

  This method will be called automatically after calling setDefaultRedisConnectionParams.

  Otherwise, you shouldn't have to call it.. Maybe as some sort of disaster-recovery call..


global RedisPools<EOL>global _defaultRedisConnectionParams<EOL>global _redisManagedConnectionParams<EOL>if not params:<EOL><INDENT>params = _defaultRedisConnectionParams<EOL>isDefaultParams = True<EOL><DEDENT>else:<EOL><INDENT>isDefaultParams = bool(params is _defaultRedisConnectionParams)<EOL><DEDENT>if '<STR_LIT>' in params:<EOL><INDENT>return params['<STR_LIT>']<EOL><DEDENT>hashValue = hashDictOneLevel(params)<EOL>if hashValue in RedisPools:<EOL><INDENT>params['<STR_LIT>'] = RedisPools[hashValue]<EOL>return RedisPools[hashValue]<EOL><DEDENT>if not isDefaultParams:<EOL><INDENT>origParams = params<EOL>params = copy.copy(params)<EOL><DEDENT>else:<EOL><INDENT>origParams = params<EOL><DEDENT>checkAgain = False<EOL>if '<STR_LIT:host>' not in params:<EOL><INDENT>if not isDefaultParams and '<STR_LIT:host>' in _defaultRedisConnectionParams:<EOL><INDENT>params['<STR_LIT:host>'] = _defaultRedisConnectionParams['<STR_LIT:host>']<EOL><DEDENT>else:<EOL><INDENT>params['<STR_LIT:host>'] = '<STR_LIT:127.0.0.1>'<EOL><DEDENT>checkAgain = True<EOL><DEDENT>if '<STR_LIT:port>' not in params:<EOL><INDENT>if not isDefaultParams and '<STR_LIT:port>' in _defaultRedisConnectionParams:<EOL><INDENT>params['<STR_LIT:port>'] = _defaultRedisConnectionParams['<STR_LIT:port>']<EOL><DEDENT>else:<EOL><INDENT>params['<STR_LIT:port>'] = <NUM_LIT><EOL><DEDENT>checkAgain = True<EOL><DEDENT>if '<STR_LIT>' not in params:<EOL><INDENT>if not isDefaultParams and '<STR_LIT>' in _defaultRedisConnectionParams:<EOL><INDENT>params['<STR_LIT>'] = _defaultRedisConnectionParams['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>params['<STR_LIT>'] = <NUM_LIT:0><EOL><DEDENT>checkAgain = True<EOL><DEDENT>if not isDefaultParams:<EOL><INDENT>otherGlobalKeys = set(_defaultRedisConnectionParams.keys()) - set(params.keys())<EOL>for otherKey in otherGlobalKeys:<EOL><INDENT>if otherKey == '<STR_LIT>':<EOL><INDENT>continue<EOL><DEDENT>params[otherKey] = _defaultRedisConnectionParams[otherKey]<EOL>checkAgain = True<EOL><DEDENT><DEDENT>if checkAgain:<EOL><INDENT>hashValue = hashDictOneLevel(params)<EOL>if hashValue in RedisPools:<EOL><INDENT>params['<STR_LIT>'] = RedisPools[hashValue]<EOL>return RedisPools[hashValue]<EOL><DEDENT><DEDENT>connectionPool = redis.ConnectionPool(**params)<EOL>origParams['<STR_LIT>'] = params['<STR_LIT>'] = connectionPool<EOL>RedisPools[hashValue] = connectionPool<EOL>origParamsHash = hashDictOneLevel(origParams)<EOL>if origParamsHash not in _redisManagedConnectionParams:<EOL><INDENT>_redisManagedConnectionParams[origParamsHash] = [origParams]<EOL><DEDENT>elif origParams not in _redisManagedConnectionParams[origParamsHash]:<EOL><INDENT>_redisManagedConnectionParams[origParamsHash].append(origParams)<EOL><DEDENT>return connectionPool<EOL>

getRedisPool - Returns and possibly also creates a Redis connection pool
        based on the REDIS_CONNECTION_PARAMS passed in.

        The goal of this method is to keep a small connection pool rolling
        to each unique Redis instance, otherwise during network issues etc
        python-redis will leak connections and in short-order can exhaust
        all the ports on a system. There's probably also some minor
        performance gain in sharing Pools.

        Will modify "params", if "host" and/or "port" are missing, will fill
        them in with defaults, and prior to return will set "connection_pool"
        on params, which will allow immediate return on the next call,
        and allow access to the pool directly from the model object.

        @param params <dict> - REDIS_CONNECTION_PARAMS - kwargs to redis.Redis

        @return redis.ConnectionPool corrosponding to this unique server.


self.validateModel()<EOL>osetattr = object.__setattr__<EOL>ogetattr = object.__getattribute__<EOL>osetattr(self, '<STR_LIT>', {})<EOL>if kwargs.get('<STR_LIT>', False) is True:<EOL><INDENT>convertFunctionName = '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>convertFunctionName = '<STR_LIT>'<EOL><DEDENT>fields = ogetattr(self, '<STR_LIT>')<EOL>for thisField in fields:<EOL><INDENT>if thisField not in kwargs:<EOL><INDENT>val = thisField.getDefaultValue()<EOL><DEDENT>else:<EOL><INDENT>val = kwargs[thisField]<EOL>val = getattr(thisField, convertFunctionName) ( val )<EOL><DEDENT>osetattr(self, thisField, val)<EOL>try:<EOL><INDENT>self._origData[thisField] = copy.deepcopy(val)<EOL><DEDENT>except:<EOL><INDENT>try:<EOL><INDENT>self._origData[thisField] = copy.copy(val)<EOL><DEDENT>except:<EOL><INDENT>try:<EOL><INDENT>deprecatedMessage("<STR_LIT>" %(self.__class__.__name__, thisField.name, val.__class__.__name__, repr(val)))<EOL><DEDENT>except Exception as reprErr:<EOL><INDENT>deprecatedMessage("<STR_LIT>" %(self.__class__.__name__, thisField.name, val.__class__.__name__, reprErr.__class__.__name__, str(reprErr)) )<EOL><DEDENT>self._origData[thisField] = val<EOL><DEDENT><DEDENT><DEDENT>_id = kwargs.get('<STR_LIT>', None)<EOL>if _id:<EOL><INDENT>_id = int(_id)<EOL><DEDENT>object.__setattr__(self, '<STR_LIT>', _id)<EOL>

__init__ - Set the values on this object. MAKE SURE YOU CALL THE SUPER HERE, or else things will not work.


oga = object.__getattribute__<EOL>if keyName not in ('<STR_LIT>', '<STR_LIT>'):<EOL><INDENT>fields = oga(self, '<STR_LIT>')<EOL>try:<EOL><INDENT>idx = fields.index(keyName)<EOL><DEDENT>except:<EOL><INDENT>idx = -<NUM_LIT:1><EOL><DEDENT>if idx != -<NUM_LIT:1>:<EOL><INDENT>value = fields[idx].fromInput(value)<EOL><DEDENT><DEDENT>object.__setattr__(self, keyName, value)<EOL>

__setattr__ - Will be used to set an attribute on this object.

  If the attribute is a field (in self.FIELDS), it will be converted via the field type's #fromInput method.

  Otherwise, it will just set the attribute on this object.


def asDict(self, includeMeta=False, forStorage=False, strKeys=False):

ret = {}<EOL>for thisField in self.FIELDS:<EOL><INDENT>val = object.__getattribute__(self, thisField)<EOL>if forStorage is True:<EOL><INDENT>val = thisField.toStorage(val)<EOL><DEDENT>if strKeys:<EOL><INDENT>ret[str(thisField)] = val<EOL><DEDENT>else:<EOL><INDENT>ret[thisField] = val<EOL><DEDENT><DEDENT>if includeMeta is True:<EOL><INDENT>ret['<STR_LIT>'] = getattr(self, '<STR_LIT>', None)<EOL><DEDENT>return ret<EOL>

toDict / asDict - Get a dictionary representation of this model.

@param includeMeta - Include metadata in return. For now, this is only pk stored as "_id"

@param convertValueTypes <bool> - default True. If False, fields with fieldValue defined will be converted to that type.
        Use True when saving, etc, as native type is always either str or bytes.

@param strKeys <bool> Default False - If True, just the string value of the field name will be used as the key.
        Otherwise, the IRField itself will be (although represented and indexed by string)

@return - Dictionary reprensetation of this object and all fields


pprint.pprint(self.asDict(includeMeta=True, forStorage=False, strKeys=True), stream=stream)<EOL>

pprint - Pretty-print a dict representation of this object.

@param stream <file/None> - Either a stream to output, or None to default to sys.stdout


if not self._id or not self._origData:<EOL><INDENT>return True<EOL><DEDENT>for thisField in self.FIELDS:<EOL><INDENT>thisVal = object.__getattribute__(self, thisField)<EOL>if self._origData.get(thisField, '<STR_LIT>') != thisVal:<EOL><INDENT>return True<EOL><DEDENT>if cascadeObjects is True and issubclass(thisField.__class__, IRForeignLinkFieldBase):<EOL><INDENT>if thisVal.objHasUnsavedChanges():<EOL><INDENT>return True<EOL><DEDENT><DEDENT><DEDENT>return False<EOL>

hasUnsavedChanges - Check if any unsaved changes are present in this model, or if it has never been saved.

@param cascadeObjects <bool> default False, if True will check if any foreign linked objects themselves have unsaved changes (recursively).
        Otherwise, will just check if the pk has changed.

@return <bool> - True if any fields have changed since last fetch, or if never saved. Otherwise, False


updatedFields = {}<EOL>for thisField in self.FIELDS:<EOL><INDENT>thisVal = object.__getattribute__(self, thisField)<EOL>if self._origData.get(thisField, '<STR_LIT>') != thisVal:<EOL><INDENT>updatedFields[thisField] = (self._origData[thisField], thisVal)<EOL><DEDENT>if cascadeObjects is True and issubclass(thisField.__class__, IRForeignLinkFieldBase) and thisVal.objHasUnsavedChanges():<EOL><INDENT>updatedFields[thisField] = (self._origData[thisField], thisVal)<EOL><DEDENT><DEDENT>return updatedFields<EOL>

getUpdatedFields - See changed fields.

@param cascadeObjects <bool> default False, if True will check if any foreign linked objects themselves have unsaved changes (recursively).
        Otherwise, will just check if the pk has changed.

@return - a dictionary of fieldName : tuple(old, new).

fieldName may be a string or may implement IRField (which implements string, and can be used just like a string)


def diff(firstObj, otherObj, includeMeta=False):

if not isIndexedRedisModel(firstObj): <EOL><INDENT>raise ValueError('<STR_LIT>' %( type(firstObj).__name__ , ) )<EOL><DEDENT>if not isIndexedRedisModel(otherObj): <EOL><INDENT>raise ValueError('<STR_LIT>' %( type(otherObj).__name__ , ) )<EOL><DEDENT>firstObj.validateModel()<EOL>otherObj.validateModel()<EOL>if getattr(firstObj, '<STR_LIT>') != getattr(otherObj, '<STR_LIT>'):<EOL><INDENT>raise ValueError('<STR_LIT>' %( firstObj.__class__, otherObj.__class__) )<EOL><DEDENT>diffFields = {}<EOL>for thisField in firstObj.FIELDS:<EOL><INDENT>thisFieldStr = str(thisField)<EOL>firstVal = object.__getattribute__( firstObj, thisFieldStr )<EOL>otherVal = object.__getattribute__( otherObj, thisFieldStr )<EOL>if firstVal != otherVal:<EOL><INDENT>diffFields[ thisFieldStr ] = ( (firstVal, otherVal) )<EOL><DEDENT><DEDENT>if includeMeta:<EOL><INDENT>firstPk = firstObj.getPk()<EOL>otherPk = otherObj.getPk()<EOL>if firstPk != otherPk:<EOL><INDENT>diffFields['<STR_LIT>'] = ( firstPk, otherPk )<EOL><DEDENT><DEDENT>return diffFields<EOL>

diff - Compare the field values on two IndexedRedisModels.

@param firstObj <IndexedRedisModel instance> - First object (or self)

@param otherObj <IndexedRedisModel instance> - Second object

@param includeMeta <bool> - If meta information (like pk) should be in the diff results.

@return <dict> - Dict of  'field' : ( value_firstObjForField, value_otherObjForField ).

        Keys are names of fields with different values.
        Value is a tuple of ( value_firstObjForField, value_otherObjForField )

Can be called statically, like: IndexedRedisModel.diff ( obj1, obj2 )

  or in reference to an obj   : obj1.diff(obj2)


return IndexedRedisQuery(cls)<EOL>


return IndexedRedisSave(cls)<EOL>

saver - Get an IndexedRedisSave associated with this model


return IndexedRedisDelete(cls)<EOL>

deleter - Get access to IndexedRedisDelete for this model.
@see IndexedRedisDelete.
Usually you'll probably just do Model.objects.filter(...).delete()


saver = IndexedRedisSave(self.__class__)<EOL>return saver.save(self, cascadeSave=cascadeSave)<EOL>

save - Save this object.

Will perform an "insert" if this object had not been saved before,
  otherwise will update JUST the fields changed on THIS INSTANCE of the model.

  i.e. If you have two processes fetch the same object and change different fields, they will not overwrite
  eachother, but only save the ones each process changed.

If you want to save multiple objects of type MyModel in a single transaction,
and you have those objects in a list, myObjs, you can do the following:

        MyModel.saver.save(myObjs)

@param cascadeSave <bool> Default True - If True, any Foreign models linked as attributes that have been altered
   or created will be saved with this object. If False, only this object (and the reference to an already-saved foreign model) will be saved.

@see #IndexedRedisSave.save

@return <list> - Single element list, id of saved object (if successful)


deleter = IndexedRedisDelete(self.__class__)<EOL>return deleter.deleteOne(self)<EOL>


return self._id<EOL>

getPk - Gets the internal primary key associated with this object


conn = cls.objects._get_new_connection()<EOL>transaction = conn.pipeline()<EOL>transaction.eval(

reset - Remove all stored data associated with this model (i.e. all objects of this type),
        and then save all the provided objects in #newObjs , all in one atomic transaction.

Use this method to move from one complete set of objects to another, where any querying applications
will only see the complete before or complete after.

@param newObjs list<IndexedRedisModel objs> - A list of objects that will replace the current dataset

To just replace a specific subset of objects in a single transaction, you can do MyModel.saver.save(objs)
  and just the objs in "objs" will be inserted/updated in one atomic step.

This method, on the other hand, will delete all previous objects and add the newly provided objects in a single atomic step,
  and also reset the primary key ID generator

@return list<int> - The new primary keys associated with each object (same order as provided #newObjs list)


def hasSameValues(self, other, cascadeObject=True):

if self.FIELDS != other.FIELDS:<EOL><INDENT>return False<EOL><DEDENT>oga = object.__getattribute__<EOL>for field in self.FIELDS:<EOL><INDENT>thisVal = oga(self, field)<EOL>otherVal = oga(other, field)<EOL>if thisVal != otherVal:<EOL><INDENT>return False<EOL><DEDENT>if cascadeObject is True and issubclass(field.__class__, IRForeignLinkFieldBase):<EOL><INDENT>if thisVal and thisVal.isFetched():<EOL><INDENT>if otherVal and otherVal.isFetched():<EOL><INDENT>theseForeign = thisVal.getObjs()<EOL>othersForeign = otherVal.getObjs()<EOL>for i in range(len(theseForeign)):<EOL><INDENT>if not theseForeign[i].hasSameValues(othersForeign[i]):<EOL><INDENT>return False<EOL><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>theseForeign = thisVal.getObjs()<EOL>for i in range(len(theseForeign)):<EOL><INDENT>if theseForeign[i].hasUnsavedChanges(cascadeObjects=True):<EOL><INDENT>return False<EOL><DEDENT><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>if otherVal and otherVal.isFetched():<EOL><INDENT>othersForeign = otherVal.getObjs()<EOL>for i in range(len(othersForeign)):<EOL><INDENT>if othersForeign[i].hasUnsavedChanges(cascadeObjects=True):<EOL><INDENT>return False<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>return True<EOL>

hasSameValues - Check if this and another model have the same fields and values.

This does NOT include id, so the models can have the same values but be different objects in the database.

@param other <IndexedRedisModel> - Another model

@param cascadeObject <bool> default True - If True, foreign link values with changes will be considered a difference.
        Otherwise, only the immediate values are checked.

@return <bool> - True if all fields have the same value, otherwise False


<EOL>if type(self) != type(other):<EOL><INDENT>return False<EOL><DEDENT>if not self.hasSameValues(other):<EOL><INDENT>return False<EOL><DEDENT>if getattr(self, '<STR_LIT>', None) != getattr(other, '<STR_LIT>', None):<EOL><INDENT>return False<EOL><DEDENT>return True<EOL>

__eq__ - Check if two IndexedRedisModels are equal.

They are equal if they have the same type and same field values (including id).

To check if two models have the same values (but can have different ids), use #hasSameValues method.


return not self.__eq__(other)<EOL>

__ne__ - Check if two IndexedRedisModels are NOT equal.

@see IndexedRedisModel.__eq__


myClassName = self.__class__.__name__<EOL>myDict = self.asDict(True, forStorage=False, strKeys=True)<EOL>_id = myDict.pop('<STR_LIT>', '<STR_LIT:None>')<EOL>myPointerLoc = "<STR_LIT>" %(id(self),)<EOL>if not _id or _id == '<STR_LIT:None>':<EOL><INDENT>return '<STR_LIT>' %(myClassName, myPointerLoc)<EOL><DEDENT>elif self.hasUnsavedChanges():<EOL><INDENT>return '<STR_LIT>' %(myClassName, to_unicode(_id), myPointerLoc)<EOL><DEDENT>return '<STR_LIT>' %(myClassName, to_unicode(_id), myPointerLoc)<EOL>

__str__ - Returns a string representation of this object's state.
    See implementation.

@return <str>-
    Some samples:
    (Pdb) str(z)
    '<Song obj _id=24 at 0x7f3c6a3a4490>'
    (Pdb) z.artist = 'New Artist'
    (Pdb) str(z)
    '<Song obj _id=24 (Unsaved Changes) at 0x7f3c6a3a4490>'


myDict = self.asDict(True, forStorage=False, strKeys=True)<EOL>myClassName = self.__class__.__name__<EOL>ret = [myClassName, '<STR_LIT:(>']<EOL>_id = myDict.pop('<STR_LIT>', '<STR_LIT>')<EOL>if _id:<EOL><INDENT>ret += ['<STR_LIT>', to_unicode(_id), '<STR_LIT>']<EOL><DEDENT>key = None<EOL>for key, value in myDict.items():<EOL><INDENT>ret += [key, '<STR_LIT:=>', repr(value), '<STR_LIT:U+002CU+0020>']<EOL><DEDENT>if key is not None or not _id:<EOL><INDENT>ret.pop()<EOL><DEDENT>ret.append('<STR_LIT:)>')<EOL>return '<STR_LIT>'.join(ret)<EOL>

__repr__ - Returns a string of the constructor/params to recreate this object.
    Example: objCopy = eval(repr(obj))

    @return - String of python init call to recreate this object


def copy(self, copyPrimaryKey=False, copyValues=False):

cpy = self.__class__(**self.asDict(copyPrimaryKey, forStorage=False))<EOL>if copyValues is True:<EOL><INDENT>for fieldName in cpy.FIELDS:<EOL><INDENT>setattr(cpy, fieldName, copy.deepcopy(getattr(cpy, fieldName)))<EOL><DEDENT><DEDENT>return cpy<EOL>

copy - Copies this object.

@param copyPrimaryKey <bool> default False - If True, any changes to the copy will save over-top the existing entry in Redis.
    If False, only the data is copied, and nothing is saved.

@param copyValues <bool> default False - If True, every field value on this object will be explicitly copied. If False,
  an object will be created with the same values, and depending on the type may share the same reference.

  This is the difference between a copy and a deepcopy.

@return <IndexedRedisModel> - Copy of this object, per above

If you need a copy that IS linked, @see IndexedRedisModel.copy


return self.copy(copyPrimaryKey=False, copyValues=False)<EOL>

__copy__ - Used by the "copy" module to make a copy,
   which will NOT be linked to the original entry in the database, but will contain the same data

@return <IndexedRedisModel> - Copy of this object, per above


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

<EOL>cpy = self.copy(copyPrimaryKey=False, copyValues=True)<EOL>cpy.FIELDS = cpy.FIELDS[:]<EOL>cpy.INDEXED_FIELDS = cpy.INDEXED_FIELDS[:]<EOL>return cpy<EOL>

__deepcopy__ - Used by the "copy" module to make a deepcopy.

   Will perform a deepcopy of all attributes, which will NOT be linked to the original entry in the database.

   If you need a copy that IS linked, @see IndexedRedisModel.copy

@return <IndexedRedisModel> - Deep copy of this object, per above


if type(redisCon) == dict:<EOL><INDENT>conn = redis.Redis(**redisCon)<EOL><DEDENT>elif hasattr(conn, '<STR_LIT>') and issubclass(conn.__class__, redis.Redis):<EOL><INDENT>conn = redisCon<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>saver = self.saver<EOL>forceID = saver._getNextID(conn) <EOL>myCopy = self.copy(False)<EOL>return saver.save(myCopy, usePipeline=True, forceID=forceID, conn=conn)<EOL>

saveToExternal - Saves this object to a different Redis than that specified by REDIS_CONNECTION_PARAMS on this model.

@param redisCon <dict/redis.Redis> - Either a dict of connection params, a la REDIS_CONNECTION_PARAMS, or an existing Redis connection.
        If you are doing a lot of bulk copies, it is recommended that you create a Redis connection and pass it in rather than establish a new
        connection with each call.

@note - You will generate a new primary key relative to the external Redis environment. If you need to reference a "shared" primary key, it is better
                to use an indexed field than the internal pk.


_id = self._id<EOL>if not _id:<EOL><INDENT>raise KeyError('<STR_LIT>')<EOL><DEDENT>currentData = self.asDict(False, forStorage=False)<EOL>newDataObj = self.objects.get(_id)<EOL>if not newDataObj:<EOL><INDENT>raise KeyError('<STR_LIT>' %(_id,))<EOL><DEDENT>newData = newDataObj.asDict(False, forStorage=False)<EOL>if currentData == newData and not self.foreignFields:<EOL><INDENT>return []<EOL><DEDENT>updatedFields = {}<EOL>for thisField, newValue in newData.items():<EOL><INDENT>defaultValue = thisField.getDefaultValue()<EOL>currentValue = currentData.get(thisField, defaultValue)<EOL>fieldIsUpdated = False<EOL>if currentValue != newValue:<EOL><INDENT>fieldIsUpdated = True<EOL><DEDENT>elif cascadeObjects is True and issubclass(thisField.__class__, IRForeignLinkFieldBase):<EOL><INDENT>if currentValue.isFetched():<EOL><INDENT>oldObjs = currentValue.getObjs()<EOL>newObjs = newValue.getObjs()<EOL>if oldObjs != newObjs: <EOL><INDENT>fieldIsUpdated = True<EOL><DEDENT>else:<EOL><INDENT>for i in range(len(oldObjs)):<EOL><INDENT>if not oldObjs[i].hasSameValues(newObjs[i], cascadeObjects=True):<EOL><INDENT>fieldIsUpdated = True<EOL>break<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>if fieldIsUpdated is True:<EOL><INDENT>updatedFields[thisField] = ( currentValue, newValue) <EOL>setattr(self, thisField, newValue)<EOL>self._origData[thisField] = newDataObj._origData[thisField]<EOL><DEDENT><DEDENT>return updatedFields<EOL>

reload - Reload this object from the database, overriding any local changes and merging in any updates.

    @param cascadeObjects <bool> Default True. If True, foreign-linked objects will be reloaded if their values have changed
      since last save/fetch. If False, only if the pk changed will the foreign linked objects be reloaded.

    @raises KeyError - if this object has not been saved (no primary key)

    @return - Dict with the keys that were updated. Key is field name that was updated,
       and value is tuple of (old value, new value).

    NOTE: Currently, this will cause a fetch of all Foreign Link objects, one level


IndexedRedisQuery._doCascadeFetch(self)<EOL>

cascadeFetch - Immediately fetch all foreign links on this field, and all their links, etc.

  Normally, this would be done on access of the foreign members, or at .all() time by passing cascadeFetch=True into
   the fetch function

   e.x.    MyModel.objects.filter(...).all(cascadeFetch=True)


myData = self.asDict(True, forStorage=False)<EOL>myData['<STR_LIT>'] = self._origData<EOL>return myData<EOL>


self.__class__.validateModel()<EOL>for key, value in stateDict.items():<EOL><INDENT>setattr(self, key, value)<EOL><DEDENT>self._origData = stateDict['<STR_LIT>']<EOL>


copyNum = _modelCopyMap[mdl]<EOL>_modelCopyMap[mdl] += <NUM_LIT:1><EOL>mdlCopy = type(mdl.__name__ + '<STR_LIT>' + str(copyNum), mdl.__bases__, copy.deepcopy(dict(mdl.__dict__)))<EOL>mdlCopy.FIELDS = [field.copy() for field in mdl.FIELDS]<EOL>mdlCopy.INDEXED_FIELDS = [str(idxField) for idxField in mdl.INDEXED_FIELDS] <EOL>mdlCopy.validateModel()<EOL>return mdlCopy<EOL>

copyModel - Copy this model, and return that copy.

  The copied model will have all the same data, but will have a fresh instance of the FIELDS array and all members,
    and the INDEXED_FIELDS array.

  This is useful for converting, like changing field types or whatever, where you can load from one model and save into the other.

@return <IndexedRedisModel> - A copy class of this model class with a unique name.


if model == IndexedRedisModel:<EOL><INDENT>import re<EOL>if re.match('<STR_LIT>', sys.argv[<NUM_LIT:0>]):<EOL><INDENT>return<EOL><DEDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>global validatedModels<EOL>keyName = model.KEY_NAME<EOL>if not keyName:<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(str(model.__name__), ) )<EOL><DEDENT>if model in validatedModels:<EOL><INDENT>return True<EOL><DEDENT>failedValidationStr = '<STR_LIT>' %(str(model.__name__), ) <EOL>fieldSet = set(model.FIELDS)<EOL>indexedFieldSet = set(model.INDEXED_FIELDS)<EOL>if not fieldSet:<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(failedValidationStr,))<EOL><DEDENT>if hasattr(model, '<STR_LIT>'):<EOL><INDENT>raise InvalidModelException('<STR_LIT>')<EOL><DEDENT>if hasattr(model, '<STR_LIT>'):<EOL><INDENT>raise InvalidModelException('<STR_LIT>')<EOL><DEDENT>newFields = []<EOL>updatedFields = []<EOL>mustUpdateFields = False<EOL>foreignFields = []<EOL>for thisField in fieldSet:<EOL><INDENT>if thisField == '<STR_LIT>':<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(failedValidationStr,))<EOL><DEDENT>try:<EOL><INDENT>codecs.ascii_encode(thisField)<EOL><DEDENT>except UnicodeDecodeError as e:<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(failedValidationStr, to_unicode(thisField), str(e)))<EOL><DEDENT>if issubclass(thisField.__class__, IRForeignLinkFieldBase):<EOL><INDENT>foreignFields.append(thisField)<EOL><DEDENT>if issubclass(thisField.__class__, IRField):<EOL><INDENT>newFields.append(thisField)<EOL><DEDENT>else:<EOL><INDENT>mustUpdateFields = True<EOL>newField = IRClassicField(thisField)<EOL>newFields.append(newField)<EOL>updatedFields.append(thisField)<EOL>thisField = newField<EOL><DEDENT>if str(thisField) == '<STR_LIT>':<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(failedValidationStr, str(type(thisField)), repr(thisField)   ) )<EOL><DEDENT>if thisField in indexedFieldSet and thisField.CAN_INDEX is False:<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(failedValidationStr, str(thisField.__class__.__name__), repr(thisField)))<EOL><DEDENT>if hasattr(IndexedRedisModel, thisField) is True:<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(failedValidationStr, str(thisField)))<EOL><DEDENT><DEDENT>if mustUpdateFields is True:<EOL><INDENT>model.FIELDS = newFields<EOL>deprecatedMessage('<STR_LIT>' %(model.__name__, repr(updatedFields)), '<STR_LIT>' + model.__name__)<EOL><DEDENT>model.FIELDS = KeyList(model.FIELDS)<EOL>if bool(indexedFieldSet - fieldSet):<EOL><INDENT>raise InvalidModelException('<STR_LIT>' %(failedValidationStr, str(list(indexedFieldSet - fieldSet)), ) )<EOL><DEDENT>model.foreignFields = foreignFields<EOL>validatedModels.add(model)<EOL>return True<EOL>

validateModel - Class method that validates a given model is implemented correctly. Will only be validated once, on first model instantiation.

@param model - Implicit of own class

@return - True

@raises - InvalidModelException if there is a problem with the model, and the message contains relevant information.


return cls.connectAlt(redisConnectionParams)<EOL>

connect - DEPRECATED NAME - @see connectAlt
  Create a class of this model which will use an alternate connection than the one specified by REDIS_CONNECTION_PARAMS on this model.

@param redisConnectionParams <dict> - Dictionary of arguments to redis.Redis, same as REDIS_CONNECTION_PARAMS.

@return - A class that can be used in all the same ways as the existing IndexedRedisModel, but that connects to a different instance.


if not isinstance(redisConnectionParams, dict):<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>hashVal = hashDictOneLevel(redisConnectionParams)<EOL>modelDictCopy = copy.deepcopy(dict(cls.__dict__))<EOL>modelDictCopy['<STR_LIT>'] = redisConnectionParams<EOL>ConnectedIndexedRedisModel = type('<STR_LIT>' + cls.__name__ + str(hashVal), cls.__bases__, modelDictCopy)<EOL>return ConnectedIndexedRedisModel<EOL>

connectAlt - Create a class of this model which will use an alternate connection than the one specified by REDIS_CONNECTION_PARAMS on this model.

@param redisConnectionParams <dict> - Dictionary of arguments to redis.Redis, same as REDIS_CONNECTION_PARAMS.

@return - A class that can be used in all the same ways as the existing IndexedRedisModel, but that connects to a different instance.

  The fields and key will be the same here, but the connection will be different. use #copyModel if you want an independent class for the model


mdl.validateModel()<EOL>self.mdl = mdl<EOL>self.keyName = mdl.KEY_NAME<EOL>fields = mdl.FIELDS<EOL>self.fields = mdl.FIELDS<EOL>self.indexedFields = [fields[fieldName] for fieldName in mdl.INDEXED_FIELDS]<EOL>self._connection = None<EOL>

Internal constructor

@param mdl - IndexedRedisModel implementer


pool = getRedisPool(self.mdl.REDIS_CONNECTION_PARAMS)<EOL>return redis.Redis(connection_pool=pool)<EOL>

_get_new_connection - Get a new connection
internal


if self._connection is None:<EOL><INDENT>self._connection = self._get_new_connection() <EOL><DEDENT>return self._connection<EOL>

_get_connection - Maybe get a new connection, or reuse if passed in.
        Will share a connection with a model
internal


return '<STR_LIT>'.join([INDEXED_REDIS_PREFIX, self.keyName + '<STR_LIT>'])<EOL>

_get_ids_key - Gets the key holding primary keys
internal


def _add_id_to_keys(self, pk, conn=None):

if conn is None:<EOL><INDENT>conn = self._get_connection()<EOL><DEDENT>conn.sadd(self._get_ids_key(), pk)<EOL>

_add_id_to_keys - Adds primary key to table
internal


def _rem_id_from_keys(self, pk, conn=None):

if conn is None:<EOL><INDENT>conn = self._get_connection()<EOL><DEDENT>conn.srem(self._get_ids_key(), pk)<EOL>

_rem_id_from_keys - Remove primary key from table
internal


def _add_id_to_index(self, indexedField, pk, val, conn=None):

if conn is None:<EOL><INDENT>conn = self._get_connection()<EOL><DEDENT>conn.sadd(self._get_key_for_index(indexedField, val), pk)<EOL>

_add_id_to_index - Adds an id to an index
internal


def _rem_id_from_index(self, indexedField, pk, val, conn=None):

if conn is None:<EOL><INDENT>conn = self._get_connection()<EOL><DEDENT>conn.srem(self._get_key_for_index(indexedField, val), pk)<EOL>

_rem_id_from_index - Removes an id from an index
internal


def _get_key_for_index(self, indexedField, val):

<EOL>if hasattr(indexedField, '<STR_LIT>'):<EOL><INDENT>val = indexedField.toIndex(val)<EOL><DEDENT>else:<EOL><INDENT>val = self.fields[indexedField].toIndex(val)<EOL><DEDENT>return '<STR_LIT>'.join( [INDEXED_REDIS_PREFIX, self.keyName, '<STR_LIT>', indexedField, '<STR_LIT::>', val] )<EOL>

_get_key_for_index - Returns the key name that would hold the indexes on a value
Internal - does not validate that indexedFields is actually indexed. Trusts you. Don't let it down.

@param indexedField - string of field name
@param val - Value of field

@return - Key name string, potentially hashed.


def _compat_get_str_key_for_index(self, indexedField, val):

return '<STR_LIT>'.join([INDEXED_REDIS_PREFIX, self.keyName, '<STR_LIT>', indexedField, '<STR_LIT::>', getattr(indexedField, '<STR_LIT>', to_unicode)(val)])<EOL>

_compat_get_str_key_for_index - Return the key name as a string, even if it is a hashed index field.
  This is used in converting unhashed fields to a hashed index (called by _compat_rem_str_id_from_index which is called by compat_convertHashedIndexes)

  @param inde
@param indexedField - string of field name
@param val - Value of field

@return - Key name string, always a string regardless of hash


@deprecated('<STR_LIT>')<EOL><INDENT>def _compat_rem_str_id_from_index(self, indexedField, pk, val, conn=None):<DEDENT>

if conn is None:<EOL><INDENT>conn = self._get_connection()<EOL><DEDENT>conn.srem(self._compat_get_str_key_for_index(indexedField, val), pk)<EOL>

_compat_rem_str_id_from_index - Used in compat_convertHashedIndexes to remove the old string repr of a field,
        in order to later add the hashed value,


return '<STR_LIT>'.join([INDEXED_REDIS_PREFIX, self.keyName, '<STR_LIT>', to_unicode(pk)])<EOL>

_get_key_for_id - Returns the key name that holds all the data for an object
Internal

@param pk - primary key

@return - Key name string


return '<STR_LIT>'.join([INDEXED_REDIS_PREFIX, self.keyName, '<STR_LIT>'])<EOL>

_get_next_id_key - Returns the key name that holds the generator for primary key values
Internal

@return - Key name string


if conn is None:<EOL><INDENT>conn = self._get_connection()<EOL><DEDENT>return to_unicode(conn.get(self._get_next_id_key()) or <NUM_LIT:0>)<EOL>

_peekNextID - Look at, but don't increment the primary key for this model.
        Internal.

@return int - next pk


if conn is None:<EOL><INDENT>conn = self._get_connection()<EOL><DEDENT>return int(conn.incr(self._get_next_id_key()))<EOL>

_getNextID - Get (and increment) the next primary key for this model.
        If you don't want to increment, @see _peekNextID .
        Internal.
        This is done automatically on save. No need to call it.

@return int - next pk


return self._get_ids_key() + '<STR_LIT>' + uuid.uuid4().__str__()<EOL>

_getTempKey - Generates a temporary key for intermediate storage


selfCopy = self.__copy__()<EOL>return IndexedRedisQuery._filter(selfCopy, **kwargs)<EOL>

filter - Add filters based on INDEXED_FIELDS having or not having a value.
  Note, no objects are actually fetched until .all() is called

        Use the field name [ model.objects.filter(some_field='value')] to filter on items containing that value.
        Use the field name suffxed with '__ne' for a negation filter [ model.objects.filter(some_field__ne='value') ]

Example:
        query = Model.objects.filter(field1='value', field2='othervalue')

        objs1 = query.filter(something__ne='value').all()
        objs2 = query.filter(something__ne=7).all()

@returns - A copy of this object, with the additional filters. If you want to work inline on this object instead, use the filterInline method.


return IndexedRedisQuery._filter(self, **kwargs)<EOL>

filterInline - @see IndexedRedisQuery.filter. This is the same as filter, but works inline on this object instead of creating a copy.
        Use this is you do not need to retain the previous filter object.


for key, value in kwargs.items():<EOL><INDENT>if key.endswith('<STR_LIT>'):<EOL><INDENT>notFilter = True<EOL>key = key[:-<NUM_LIT:4>]<EOL><DEDENT>else:<EOL><INDENT>notFilter = False<EOL><DEDENT>if key not in filterObj.indexedFields:<EOL><INDENT>raise ValueError('<STR_LIT>' + key + '<STR_LIT>')<EOL><DEDENT>if notFilter is False:<EOL><INDENT>filterObj.filters.append( (key, value) )<EOL><DEDENT>else:<EOL><INDENT>filterObj.notFilters.append( (key, value) )<EOL><DEDENT><DEDENT>return filterObj<EOL>

Internal for handling filters; the guts of .filter and .filterInline


conn = self._get_connection()<EOL>numFilters = len(self.filters)<EOL>numNotFilters = len(self.notFilters)<EOL>if numFilters + numNotFilters == <NUM_LIT:0>:<EOL><INDENT>return conn.scard(self._get_ids_key())<EOL><DEDENT>if numNotFilters == <NUM_LIT:0>:<EOL><INDENT>if numFilters == <NUM_LIT:1>:<EOL><INDENT>(filterFieldName, filterValue) = self.filters[<NUM_LIT:0>]<EOL>return conn.scard(self._get_key_for_index(filterFieldName, filterValue))<EOL><DEDENT>indexKeys = [self._get_key_for_index(filterFieldName, filterValue) for filterFieldName, filterValue in self.filters]<EOL>return len(conn.sinter(indexKeys))<EOL><DEDENT>notIndexKeys = [self._get_key_for_index(filterFieldName, filterValue) for filterFieldName, filterValue in self.notFilters]<EOL>if numFilters == <NUM_LIT:0>:<EOL><INDENT>return len(conn.sdiff(self._get_ids_key(), *notIndexKeys))<EOL><DEDENT>indexKeys = [self._get_key_for_index(filterFieldName, filterValue) for filterFieldName, filterValue in self.filters]<EOL>tempKey = self._getTempKey()<EOL>pipeline = conn.pipeline()<EOL>pipeline.sinterstore(tempKey, *indexKeys)<EOL>pipeline.sdiff(tempKey, *notIndexKeys)<EOL>pipeline.delete(tempKey)<EOL>pks = pipeline.execute()[<NUM_LIT:1>] <EOL>return len(pks)<EOL>

count - gets the number of records matching the filter criteria

Example:
        theCount = Model.objects.filter(field1='value').count()


conn = self._get_connection()<EOL>key = self._get_key_for_id(pk)<EOL>return conn.exists(key)<EOL>

exists - Tests whether a record holding the given primary key exists.

@param pk - Primary key (see getPk method)

Example usage: Waiting for an object to be deleted without fetching the object or running a filter.

This is a very cheap operation.

@return <bool> - True if object with given pk exists, otherwise False


conn = self._get_connection()<EOL>numFilters = len(self.filters)<EOL>numNotFilters = len(self.notFilters)<EOL>if numFilters + numNotFilters == <NUM_LIT:0>:<EOL><INDENT>conn = self._get_connection()<EOL>matchedKeys = conn.smembers(self._get_ids_key())<EOL><DEDENT>elif numNotFilters == <NUM_LIT:0>:<EOL><INDENT>if numFilters == <NUM_LIT:1>:<EOL><INDENT>(filterFieldName, filterValue) = self.filters[<NUM_LIT:0>]<EOL>matchedKeys = conn.smembers(self._get_key_for_index(filterFieldName, filterValue))<EOL><DEDENT>else:<EOL><INDENT>indexKeys = [self._get_key_for_index(filterFieldName, filterValue) for filterFieldName, filterValue in self.filters]<EOL>matchedKeys = conn.sinter(indexKeys)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>notIndexKeys = [self._get_key_for_index(filterFieldName, filterValue) for filterFieldName, filterValue in self.notFilters]<EOL>if numFilters == <NUM_LIT:0>:<EOL><INDENT>matchedKeys = conn.sdiff(self._get_ids_key(), *notIndexKeys)<EOL><DEDENT>else:<EOL><INDENT>indexKeys = [self._get_key_for_index(filterFieldName, filterValue) for filterFieldName, filterValue in self.filters]<EOL>tempKey = self._getTempKey()<EOL>pipeline = conn.pipeline()<EOL>pipeline.sinterstore(tempKey, *indexKeys)<EOL>pipeline.sdiff(tempKey, *notIndexKeys)<EOL>pipeline.delete(tempKey)<EOL>matchedKeys = pipeline.execute()[<NUM_LIT:1>] <EOL><DEDENT><DEDENT>matchedKeys = [ int(_key) for _key in matchedKeys ]<EOL>if sortByAge is False:<EOL><INDENT>return list(matchedKeys)<EOL><DEDENT>else:<EOL><INDENT>matchedKeys = list(matchedKeys)<EOL>matchedKeys.sort()<EOL>return matchedKeys<EOL><DEDENT>

getPrimaryKeys - Returns all primary keys matching current filterset.

@param sortByAge <bool> - If False, return will be a set and may not be ordered.
        If True, return will be a list and is guarenteed to represent objects oldest->newest

@return <set> - A set of all primary keys associated with current filters.


matchedKeys = self.getPrimaryKeys()<EOL>if matchedKeys:<EOL><INDENT>return self.getMultiple(matchedKeys, cascadeFetch=cascadeFetch)<EOL><DEDENT>return IRQueryableList([], mdl=self.mdl)<EOL>

all - Get the underlying objects which match the filter criteria.

Example:   objs = Model.objects.filter(field1='value', field2='value2').all()

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@return - Objects of the Model instance associated with this query.


matchedKeys = self.getPrimaryKeys(sortByAge=True)<EOL>if matchedKeys:<EOL><INDENT>return self.getMultiple(matchedKeys, cascadeFetch=cascadeFetch)<EOL><DEDENT>return IRQueryableList([], mdl=self.mdl)<EOL>

allByAge - Get the underlying objects which match the filter criteria, ordered oldest -> newest
        If you are doing a queue or just need the head/tail, consider .first() and .last() instead.

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@return - Objects of the Model instance associated with this query, sorted oldest->newest


def allOnlyFields(self, fields, cascadeFetch=False):

matchedKeys = self.getPrimaryKeys()<EOL>if matchedKeys:<EOL><INDENT>return self.getMultipleOnlyFields(matchedKeys, fields, cascadeFetch=cascadeFetch)<EOL><DEDENT>return IRQueryableList([], mdl=self.mdl)<EOL>

allOnlyFields - Get the objects which match the filter criteria, only fetching given fields.

@param fields - List of fields to fetch

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@return - Partial objects with only the given fields fetched


matchedKeys = self.getPrimaryKeys()<EOL>if matchedKeys:<EOL><INDENT>return self.getMultipleOnlyIndexedFields(matchedKeys)<EOL><DEDENT>return IRQueryableList([], mdl=self.mdl)<EOL>

allOnlyIndexedFields - Get the objects which match the filter criteria, only fetching indexed fields.

@return - Partial objects with only the indexed fields fetched


obj = None<EOL>matchedKeys = self.getPrimaryKeys(sortByAge=True)<EOL>if matchedKeys:<EOL><INDENT>while matchedKeys and obj is None:<EOL><INDENT>obj = self.get(matchedKeys.pop(<NUM_LIT:0>), cascadeFetch=cascadeFetch)<EOL><DEDENT><DEDENT>return obj<EOL>

First - Returns the oldest record (lowerst primary key) with current filters.
        This makes an efficient queue, as it only fetches a single object.

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@return - Instance of Model object, or None if no items match current filters


obj = None<EOL>matchedKeys = self.getPrimaryKeys(sortByAge=True)<EOL>if matchedKeys:<EOL><INDENT>while matchedKeys and obj is None:<EOL><INDENT>obj = self.get(matchedKeys.pop(), cascadeFetch=cascadeFetch)<EOL><DEDENT><DEDENT>return obj<EOL>

Last - Returns the newest record (highest primary key) with current filters.
        This makes an efficient queue, as it only fetches a single object.

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@return - Instance of Model object, or None if no items match current filters


matchedKeys = list(self.getPrimaryKeys())<EOL>obj = None<EOL>while matchedKeys and not obj:<EOL><INDENT>key = matchedKeys.pop(random.randint(<NUM_LIT:0>, len(matchedKeys)-<NUM_LIT:1>))<EOL>obj = self.get(key, cascadeFetch=cascadeFetch)<EOL><DEDENT>return obj<EOL>

Random - Returns a random record in current filterset.

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@return - Instance of Model object, or None if no items math current filters


if self.filters or self.notFilters:<EOL><INDENT>return self.mdl.deleter.deleteMultiple(self.allOnlyIndexedFields())<EOL><DEDENT>return self.mdl.deleter.destroyModel()<EOL>

delete - Deletes all entries matching the filter criteria


conn = self._get_connection()<EOL>key = self._get_key_for_id(pk)<EOL>res = conn.hgetall(key)<EOL>if type(res) != dict or not len(res.keys()):<EOL><INDENT>return None<EOL><DEDENT>res['<STR_LIT>'] = pk<EOL>ret = self._redisResultToObj(res)<EOL>if cascadeFetch is True:<EOL><INDENT>self._doCascadeFetch(ret)<EOL><DEDENT>return ret<EOL>

get - Get a single value with the internal primary key.

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@param pk - internal primary key (can be found via .getPk() on an item)


obj.validateModel()<EOL>if not obj.foreignFields:<EOL><INDENT>return<EOL><DEDENT>NOTE: Currently this fetches using one transaction per object. Implementation for actual resolution is in<EOL><INDENT>IndexedRedisModel.__getattribute__ <EOL><DEDENT>for foreignField in obj.foreignFields:<EOL><INDENT>subObjsData = object.__getattribute__(obj, foreignField)<EOL>if not subObjsData:<EOL><INDENT>setattr(obj, str(foreignField), irNull)<EOL>continue<EOL><DEDENT>subObjs = subObjsData.getObjs()<EOL>for subObj in subObjs:<EOL><INDENT>if isIndexedRedisModel(subObj):<EOL><INDENT>IndexedRedisQuery._doCascadeFetch(subObj)<EOL><DEDENT><DEDENT><DEDENT>

_doCascadeFetch - Takes an object and performs a cascading fetch on all foreign links, and all theirs, and so on.

@param obj <IndexedRedisModel> - A fetched model


def getMultiple(self, pks, cascadeFetch=False):

if type(pks) == set:<EOL><INDENT>pks = list(pks)<EOL><DEDENT>if len(pks) == <NUM_LIT:1>:<EOL><INDENT>return IRQueryableList([self.get(pks[<NUM_LIT:0>], cascadeFetch=cascadeFetch)], mdl=self.mdl)<EOL><DEDENT>conn = self._get_connection()<EOL>pipeline = conn.pipeline()<EOL>for pk in pks:<EOL><INDENT>key = self._get_key_for_id(pk)<EOL>pipeline.hgetall(key)<EOL><DEDENT>res = pipeline.execute()<EOL>ret = IRQueryableList(mdl=self.mdl)<EOL>i = <NUM_LIT:0><EOL>pksLen = len(pks)<EOL>while i < pksLen:<EOL><INDENT>if res[i] is None:<EOL><INDENT>ret.append(None)<EOL>i += <NUM_LIT:1><EOL>continue<EOL><DEDENT>res[i]['<STR_LIT>'] = pks[i]<EOL>obj = self._redisResultToObj(res[i])<EOL>ret.append(obj)<EOL>i += <NUM_LIT:1><EOL><DEDENT>if cascadeFetch is True:<EOL><INDENT>for obj in ret:<EOL><INDENT>if not obj:<EOL><INDENT>continue<EOL><DEDENT>self._doCascadeFetch(obj)<EOL><DEDENT><DEDENT>return ret<EOL>

getMultiple - Gets multiple objects with a single atomic operation

@param cascadeFetch <bool> Default False, If True, all Foreign objects associated with this model
   will be fetched immediately. If False, foreign objects will be fetched on-access.

@param pks - list of internal keys