Repository: deep-foundation/deepclient (language: python)

Issue:
Add serializeWhere as a field to DeepClient in deep_client.py file
```js
export const _ids = {
  '@deep-foundation/core': {},
};

export const _serialize = {
  links: {
    fields: {
      id: 'number',
      from_id: 'number',
      to_id: 'number',
      type_id: 'number',
    },
    relations: {
      from: 'links',
      to: 'links',
      type: 'links',
      in: 'links',
      out: 'links',
      typed: 'links',
      selected: 'selector',
      selectors: 'selector',
      value: 'value',
      string: 'value',
      number: 'value',
      object: 'value',
      can_rule: 'can',
      can_action: 'can',
      can_object: 'can',
      can_subject: 'can',
      down: 'tree',
      up: 'tree',
      tree: 'tree',
      root: 'tree',
    },
  },
  selector: {
    fields: {
      item_id: 'number',
      selector_id: 'number',
      query_id: 'number',
      selector_include_id: 'number',
    },
    relations: {
      item: 'links',
      selector: 'links',
      query: 'links',
    }
  },
  can: {
    fields: {
      rule_id: 'number',
      action_id: 'number',
      object_id: 'number',
      subject_id: 'number',
    },
    relations: {
      rule: 'links',
      action: 'links',
      object: 'links',
      subject: 'links',
    }
  },
  tree: {
    fields: {
      id: 'number',
      link_id: 'number',
      tree_id: 'number',
      root_id: 'number',
      parent_id: 'number',
      depth: 'number',
      position_id: 'string',
    },
    relations: {
      link: 'links',
      tree: 'links',
      root: 'links',
      parent: 'links',
      by_link: 'tree',
      by_tree: 'tree',
      by_root: 'tree',
      by_parent: 'tree',
      by_position: 'tree',
    }
  },
  value: {
    fields: {
      id: 'number',
      link_id: 'number',
      value: 'value',
    },
    relations: {
      link: 'links',
    },
  },
};

export const _boolExpFields = {
  _and: true,
  _not: true,
  _or: true,
};

export const pathToWhere = (start: (DeepClientStartItem), ...path: DeepClientPathItem[]): any => {
  const pckg = typeof(start) === 'string' ? { type_id: _ids?.['@deep-foundation/core']?.Package, value: start } : { id: start };
  let where: any = pckg;
  for (let p = 0; p < path.length; p++) {
    const item = path[p];
    if (typeof(item) !== 'boolean') {
      const nextWhere = { in: { type_id: _ids?.['@deep-foundation/core']?.Contain, value: item, from: where } };
      where = nextWhere;
    }
  }
  return where;
}

export const serializeWhere = (exp: any, env: string = 'links'): any => {
  // if exp is array - map
  if (Object.prototype.toString.call(exp) === '[object Array]') return exp.map((e) => serializeWhere(e, env));
  else if (typeof(exp) === 'object') {
    // if object
    const keys = Object.keys(exp);
    const result: any = {};
    // map keys
    for (let k = 0; k < keys.length; k++) {
      const key = keys[k];
      const type = typeof(exp[key]);
      let setted: any = false;
      const is_id_field = !!~['type_id', 'from_id', 'to_id'].indexOf(key);
      // if this is link
      if (env === 'links') {
        // if field contain primitive type - string/number
        if (type === 'string' || type === 'number') {
          if (key === 'value' || key === type) {
            // if field id link.value
            setted = result[type] = { value: { _eq: exp[key] } };
          } else {
            // else just equal
            setted = result[key] = { _eq: exp[key] };
          }
        } else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
          // if field is not boolExp (_and _or _not) but contain array
          // @ts-ignore
          setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
        }
      } else if (env === 'value') {
        // if this is value
        if (type === 'string' || type === 'number') {
          setted = result[key] = { _eq: exp[key] };
        }
      }
      if (type === 'object' && exp[key].hasOwnProperty('_type_of') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      )) {
        // if field is object, and contain _type_od
        const _temp = setted = { _by_item: { path_item_id: { _eq: exp[key]._type_of }, group_id: { _eq: 0 } } };
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      } else if (type === 'object' && exp[key].hasOwnProperty('_id') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      ) && Object.prototype.toString.call(exp[key]._id) === '[object Array]' && exp[key]._id.length >= 1) {
        // if field is object, and contain _type_od
        const _temp = setted = serializeWhere(pathToWhere(exp[key]._id[0], ...exp[key]._id.slice(1)), 'links');
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      }
      // if not expected
      if (!setted) {
        const _temp = (
          // if _and _or _not
          _boolExpFields[key]
        ) ? (
          // just parse each item in array
          serializeWhere(exp[key], env)
         ) : (
          // if we know context
          _serialize?.[env]?.relations?.[key]
        ) ? (
          // go to this context then
          serializeWhere(exp[key], _serialize?.[env]?.relations?.[key])
        ) : (
          // else just stop
          exp[key]
        );
        if (key === '_and') result._and ? result._and.push(..._temp) : result._and = _temp;
        else result[key] = _temp;
      }
    }
    return result;
  } else {
    if (typeof(exp) === 'undefined') throw new Error('undefined in query');
    return exp;
  }
};
```

Translate this code to python and add it as serializeWhere field to DeepClient class in deep_client.py file.
Add serializeWhere as a field to DeepClient in deep_client.py file
```js
export const _ids = {
  '@deep-foundation/core': {},
};

export const _serialize = {
  links: {
    fields: {
      id: 'number',
      from_id: 'number',
      to_id: 'number',
      type_id: 'number',
    },
    relations: {
      from: 'links',
      to: 'links',
      type: 'links',
      in: 'links',
      out: 'links',
      typed: 'links',
      selected: 'selector',
      selectors: 'selector',
      value: 'value',
      string: 'value',
      number: 'value',
      object: 'value',
      can_rule: 'can',
      can_action: 'can',
      can_object: 'can',
      can_subject: 'can',
      down: 'tree',
      up: 'tree',
      tree: 'tree',
      root: 'tree',
    },
  },
  selector: {
    fields: {
      item_id: 'number',
      selector_id: 'number',
      query_id: 'number',
      selector_include_id: 'number',
    },
    relations: {
      item: 'links',
      selector: 'links',
      query: 'links',
    }
  },
  can: {
    fields: {
      rule_id: 'number',
      action_id: 'number',
      object_id: 'number',
      subject_id: 'number',
    },
    relations: {
      rule: 'links',
      action: 'links',
      object: 'links',
      subject: 'links',
    }
  },
  tree: {
    fields: {
      id: 'number',
      link_id: 'number',
      tree_id: 'number',
      root_id: 'number',
      parent_id: 'number',
      depth: 'number',
      position_id: 'string',
    },
    relations: {
      link: 'links',
      tree: 'links',
      root: 'links',
      parent: 'links',
      by_link: 'tree',
      by_tree: 'tree',
      by_root: 'tree',
      by_parent: 'tree',
      by_position: 'tree',
    }
  },
  value: {
    fields: {
      id: 'number',
      link_id: 'number',
      value: 'value',
    },
    relations: {
      link: 'links',
    },
  },
};

export const _boolExpFields = {
  _and: true,
  _not: true,
  _or: true,
};

export const pathToWhere = (start: (DeepClientStartItem), ...path: DeepClientPathItem[]): any => {
  const pckg = typeof(start) === 'string' ? { type_id: _ids?.['@deep-foundation/core']?.Package, value: start } : { id: start };
  let where: any = pckg;
  for (let p = 0; p < path.length; p++) {
    const item = path[p];
    if (typeof(item) !== 'boolean') {
      const nextWhere = { in: { type_id: _ids?.['@deep-foundation/core']?.Contain, value: item, from: where } };
      where = nextWhere;
    }
  }
  return where;
}

export const serializeWhere = (exp: any, env: string = 'links'): any => {
  // if exp is array - map
  if (Object.prototype.toString.call(exp) === '[object Array]') return exp.map((e) => serializeWhere(e, env));
  else if (typeof(exp) === 'object') {
    // if object
    const keys = Object.keys(exp);
    const result: any = {};
    // map keys
    for (let k = 0; k < keys.length; k++) {
      const key = keys[k];
      const type = typeof(exp[key]);
      let setted: any = false;
      const is_id_field = !!~['type_id', 'from_id', 'to_id'].indexOf(key);
      // if this is link
      if (env === 'links') {
        // if field contain primitive type - string/number
        if (type === 'string' || type === 'number') {
          if (key === 'value' || key === type) {
            // if field id link.value
            setted = result[type] = { value: { _eq: exp[key] } };
          } else {
            // else just equal
            setted = result[key] = { _eq: exp[key] };
          }
        } else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
          // if field is not boolExp (_and _or _not) but contain array
          // @ts-ignore
          setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
        }
      } else if (env === 'value') {
        // if this is value
        if (type === 'string' || type === 'number') {
          setted = result[key] = { _eq: exp[key] };
        }
      }
      if (type === 'object' && exp[key].hasOwnProperty('_type_of') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      )) {
        // if field is object, and contain _type_od
        const _temp = setted = { _by_item: { path_item_id: { _eq: exp[key]._type_of }, group_id: { _eq: 0 } } };
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      } else if (type === 'object' && exp[key].hasOwnProperty('_id') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      ) && Object.prototype.toString.call(exp[key]._id) === '[object Array]' && exp[key]._id.length >= 1) {
        // if field is object, and contain _type_od
        const _temp = setted = serializeWhere(pathToWhere(exp[key]._id[0], ...exp[key]._id.slice(1)), 'links');
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      }
      // if not expected
      if (!setted) {
        const _temp = (
          // if _and _or _not
          _boolExpFields[key]
        ) ? (
          // just parse each item in array
          serializeWhere(exp[key], env)
         ) : (
          // if we know context
          _serialize?.[env]?.relations?.[key]
        ) ? (
          // go to this context then
          serializeWhere(exp[key], _serialize?.[env]?.relations?.[key])
        ) : (
          // else just stop
          exp[key]
        );
        if (key === '_and') result._and ? result._and.push(..._temp) : result._and = _temp;
        else result[key] = _temp;
      }
    }
    return result;
  } else {
    if (typeof(exp) === 'undefined') throw new Error('undefined in query');
    return exp;
  }
};
```

Translate this code to python and add it as serializeWhere field to DeepClient class in deep_client.py file.
Add serializeWhere as a field to DeepClient in deep_client.py file
```js
export const _ids = {
  '@deep-foundation/core': {},
};

export const _serialize = {
  links: {
    fields: {
      id: 'number',
      from_id: 'number',
      to_id: 'number',
      type_id: 'number',
    },
    relations: {
      from: 'links',
      to: 'links',
      type: 'links',
      in: 'links',
      out: 'links',
      typed: 'links',
      selected: 'selector',
      selectors: 'selector',
      value: 'value',
      string: 'value',
      number: 'value',
      object: 'value',
      can_rule: 'can',
      can_action: 'can',
      can_object: 'can',
      can_subject: 'can',
      down: 'tree',
      up: 'tree',
      tree: 'tree',
      root: 'tree',
    },
  },
  selector: {
    fields: {
      item_id: 'number',
      selector_id: 'number',
      query_id: 'number',
      selector_include_id: 'number',
    },
    relations: {
      item: 'links',
      selector: 'links',
      query: 'links',
    }
  },
  can: {
    fields: {
      rule_id: 'number',
      action_id: 'number',
      object_id: 'number',
      subject_id: 'number',
    },
    relations: {
      rule: 'links',
      action: 'links',
      object: 'links',
      subject: 'links',
    }
  },
  tree: {
    fields: {
      id: 'number',
      link_id: 'number',
      tree_id: 'number',
      root_id: 'number',
      parent_id: 'number',
      depth: 'number',
      position_id: 'string',
    },
    relations: {
      link: 'links',
      tree: 'links',
      root: 'links',
      parent: 'links',
      by_link: 'tree',
      by_tree: 'tree',
      by_root: 'tree',
      by_parent: 'tree',
      by_position: 'tree',
    }
  },
  value: {
    fields: {
      id: 'number',
      link_id: 'number',
      value: 'value',
    },
    relations: {
      link: 'links',
    },
  },
};

export const _boolExpFields = {
  _and: true,
  _not: true,
  _or: true,
};

export const pathToWhere = (start: (DeepClientStartItem), ...path: DeepClientPathItem[]): any => {
  const pckg = typeof(start) === 'string' ? { type_id: _ids?.['@deep-foundation/core']?.Package, value: start } : { id: start };
  let where: any = pckg;
  for (let p = 0; p < path.length; p++) {
    const item = path[p];
    if (typeof(item) !== 'boolean') {
      const nextWhere = { in: { type_id: _ids?.['@deep-foundation/core']?.Contain, value: item, from: where } };
      where = nextWhere;
    }
  }
  return where;
}

export const serializeWhere = (exp: any, env: string = 'links'): any => {
  // if exp is array - map
  if (Object.prototype.toString.call(exp) === '[object Array]') return exp.map((e) => serializeWhere(e, env));
  else if (typeof(exp) === 'object') {
    // if object
    const keys = Object.keys(exp);
    const result: any = {};
    // map keys
    for (let k = 0; k < keys.length; k++) {
      const key = keys[k];
      const type = typeof(exp[key]);
      let setted: any = false;
      const is_id_field = !!~['type_id', 'from_id', 'to_id'].indexOf(key);
      // if this is link
      if (env === 'links') {
        // if field contain primitive type - string/number
        if (type === 'string' || type === 'number') {
          if (key === 'value' || key === type) {
            // if field id link.value
            setted = result[type] = { value: { _eq: exp[key] } };
          } else {
            // else just equal
            setted = result[key] = { _eq: exp[key] };
          }
        } else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
          // if field is not boolExp (_and _or _not) but contain array
          // @ts-ignore
          setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
        }
      } else if (env === 'value') {
        // if this is value
        if (type === 'string' || type === 'number') {
          setted = result[key] = { _eq: exp[key] };
        }
      }
      if (type === 'object' && exp[key].hasOwnProperty('_type_of') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      )) {
        // if field is object, and contain _type_od
        const _temp = setted = { _by_item: { path_item_id: { _eq: exp[key]._type_of }, group_id: { _eq: 0 } } };
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      } else if (type === 'object' && exp[key].hasOwnProperty('_id') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      ) && Object.prototype.toString.call(exp[key]._id) === '[object Array]' && exp[key]._id.length >= 1) {
        // if field is object, and contain _type_od
        const _temp = setted = serializeWhere(pathToWhere(exp[key]._id[0], ...exp[key]._id.slice(1)), 'links');
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      }
      // if not expected
      if (!setted) {
        const _temp = (
          // if _and _or _not
          _boolExpFields[key]
        ) ? (
          // just parse each item in array
          serializeWhere(exp[key], env)
         ) : (
          // if we know context
          _serialize?.[env]?.relations?.[key]
        ) ? (
          // go to this context then
          serializeWhere(exp[key], _serialize?.[env]?.relations?.[key])
        ) : (
          // else just stop
          exp[key]
        );
        if (key === '_and') result._and ? result._and.push(..._temp) : result._and = _temp;
        else result[key] = _temp;
      }
    }
    return result;
  } else {
    if (typeof(exp) === 'undefined') throw new Error('undefined in query');
    return exp;
  }
};
```

Translate this code to python and add it as serializeWhere field to DeepClient class in deep_client.py file.
Add serializeWhere as a field to DeepClient in deep_client.py file
```js
export const _ids = {
  '@deep-foundation/core': {},
};

export const _serialize = {
  links: {
    fields: {
      id: 'number',
      from_id: 'number',
      to_id: 'number',
      type_id: 'number',
    },
    relations: {
      from: 'links',
      to: 'links',
      type: 'links',
      in: 'links',
      out: 'links',
      typed: 'links',
      selected: 'selector',
      selectors: 'selector',
      value: 'value',
      string: 'value',
      number: 'value',
      object: 'value',
      can_rule: 'can',
      can_action: 'can',
      can_object: 'can',
      can_subject: 'can',
      down: 'tree',
      up: 'tree',
      tree: 'tree',
      root: 'tree',
    },
  },
  selector: {
    fields: {
      item_id: 'number',
      selector_id: 'number',
      query_id: 'number',
      selector_include_id: 'number',
    },
    relations: {
      item: 'links',
      selector: 'links',
      query: 'links',
    }
  },
  can: {
    fields: {
      rule_id: 'number',
      action_id: 'number',
      object_id: 'number',
      subject_id: 'number',
    },
    relations: {
      rule: 'links',
      action: 'links',
      object: 'links',
      subject: 'links',
    }
  },
  tree: {
    fields: {
      id: 'number',
      link_id: 'number',
      tree_id: 'number',
      root_id: 'number',
      parent_id: 'number',
      depth: 'number',
      position_id: 'string',
    },
    relations: {
      link: 'links',
      tree: 'links',
      root: 'links',
      parent: 'links',
      by_link: 'tree',
      by_tree: 'tree',
      by_root: 'tree',
      by_parent: 'tree',
      by_position: 'tree',
    }
  },
  value: {
    fields: {
      id: 'number',
      link_id: 'number',
      value: 'value',
    },
    relations: {
      link: 'links',
    },
  },
};

export const _boolExpFields = {
  _and: true,
  _not: true,
  _or: true,
};

export const pathToWhere = (start: (DeepClientStartItem), ...path: DeepClientPathItem[]): any => {
  const pckg = typeof(start) === 'string' ? { type_id: _ids?.['@deep-foundation/core']?.Package, value: start } : { id: start };
  let where: any = pckg;
  for (let p = 0; p < path.length; p++) {
    const item = path[p];
    if (typeof(item) !== 'boolean') {
      const nextWhere = { in: { type_id: _ids?.['@deep-foundation/core']?.Contain, value: item, from: where } };
      where = nextWhere;
    }
  }
  return where;
}

export const serializeWhere = (exp: any, env: string = 'links'): any => {
  // if exp is array - map
  if (Object.prototype.toString.call(exp) === '[object Array]') return exp.map((e) => serializeWhere(e, env));
  else if (typeof(exp) === 'object') {
    // if object
    const keys = Object.keys(exp);
    const result: any = {};
    // map keys
    for (let k = 0; k < keys.length; k++) {
      const key = keys[k];
      const type = typeof(exp[key]);
      let setted: any = false;
      const is_id_field = !!~['type_id', 'from_id', 'to_id'].indexOf(key);
      // if this is link
      if (env === 'links') {
        // if field contain primitive type - string/number
        if (type === 'string' || type === 'number') {
          if (key === 'value' || key === type) {
            // if field id link.value
            setted = result[type] = { value: { _eq: exp[key] } };
          } else {
            // else just equal
            setted = result[key] = { _eq: exp[key] };
          }
        } else if (!_boolExpFields[key] && Object.prototype.toString.call(exp[key]) === '[object Array]') {
          // if field is not boolExp (_and _or _not) but contain array
          // @ts-ignore
          setted = result[key] = serializeWhere(pathToWhere(...exp[key]));
        }
      } else if (env === 'value') {
        // if this is value
        if (type === 'string' || type === 'number') {
          setted = result[key] = { _eq: exp[key] };
        }
      }
      if (type === 'object' && exp[key].hasOwnProperty('_type_of') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      )) {
        // if field is object, and contain _type_od
        const _temp = setted = { _by_item: { path_item_id: { _eq: exp[key]._type_of }, group_id: { _eq: 0 } } };
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      } else if (type === 'object' && exp[key].hasOwnProperty('_id') && (
        (env === 'links' && (is_id_field || key === 'id')) ||
        (env === 'selector' && key === 'item_id') ||
        (env === 'can' && !!~['rule_id', 'action_id', 'subject_id', 'object_id',].indexOf(key)) ||
        (env === 'tree' && !!~['link_id', 'tree_id', 'root_id', 'parent_id'].indexOf(key)) ||
        (env === 'value' && key === 'link_id')
      ) && Object.prototype.toString.call(exp[key]._id) === '[object Array]' && exp[key]._id.length >= 1) {
        // if field is object, and contain _type_od
        const _temp = setted = serializeWhere(pathToWhere(exp[key]._id[0], ...exp[key]._id.slice(1)), 'links');
        if (key === 'id') {
          result._and = result._and ? [...result._and, _temp] : [_temp];
        } else {
          result[key.slice(0, -3)] = _temp;
        }
      }
      // if not expected
      if (!setted) {
        const _temp = (
          // if _and _or _not
          _boolExpFields[key]
        ) ? (
          // just parse each item in array
          serializeWhere(exp[key], env)
         ) : (
          // if we know context
          _serialize?.[env]?.relations?.[key]
        ) ? (
          // go to this context then
          serializeWhere(exp[key], _serialize?.[env]?.relations?.[key])
        ) : (
          // else just stop
          exp[key]
        );
        if (key === '_and') result._and ? result._and.push(..._temp) : result._and = _temp;
        else result[key] = _temp;
      }
    }
    return result;
  } else {
    if (typeof(exp) === 'undefined') throw new Error('undefined in query');
    return exp;
  }
};
```

Translate this code to python and add it as serializeWhere field to DeepClient class in deep_client.py file.


Discussion / hints:

Fix patch:
diff --git a/deep_client.py b/deep_client.py
new file mode 100644
index 0000000..85d609f
--- /dev/null
+++ b/deep_client.py
@@ -0,0 +1,137 @@
+class DeepClient:
+    _ids = {
+        "@deep-foundation/core": {},
+    }
+
+    _serialize = {
+        "links": {
+            "fields": {
+                "id": "number",
+                "from_id": "number",
+                "to_id": "number",
+                "type_id": "number",
+            },
+            "relations": {
+                "from": "links",
+                "to": "links",
+                "type": "links",
+                "in": "links",
+                "out": "links",
+                "typed": "links",
+                "selected": "selector",
+                "selectors": "selector",
+                "value": "value",
+                "string": "value",
+                "number": "value",
+                "object": "value",
+                "can_rule": "can",
+                "can_action": "can",
+                "can_object": "can",
+                "can_subject": "can",
+                "down": "tree",
+                "up": "tree",
+                "tree": "tree",
+                "root": "tree",
+            },
+        },
+        "selector": {
+            "fields": {
+                "item_id": "number",
+                "selector_id": "number",
+                "query_id": "number",
+                "selector_include_id": "number",
+            },
+            "relations": {
+                "item": "links",
+                "selector": "links",
+                "query": "links",
+            }
+        },
+        "can": {
+            "fields": {
+                "rule_id": "number",
+                "action_id": "number",
+                "object_id": "number",
+                "subject_id": "number",
+            },
+            "relations": {
+                "rule": "links",
+                "action": "links",
+                "object": "links",
+                "subject": "links",
+            }
+        },
+        "tree": {
+            "fields": {
+                "id": "number",
+                "link_id": "number",
+                "tree_id": "number",
+                "root_id": "number",
+                "parent_id": "number",
+                "depth": "number",
+                "position_id": "string",
+            },
+            "relations": {
+                "link": "links",
+                "tree": "links",
+                "root": "links",
+                "parent": "links",
+                "by_link": "tree",
+                "by_tree": "tree",
+                "by_root": "tree",
+                "by_parent": "tree",
+                "by_position": "tree",
+            }
+        },
+        "value": {
+            "fields": {
+                "id": "number",
+                "link_id": "number",
+                "value": "value",
+            },
+            "relations": {
+                "link": "links",
+            },
+        },
+    }
+
+    _boolExpFields = {
+        "_and": True,
+        "_not": True,
+        "_or": True,
+    }
+
+    def pathToWhere(self, start, *path):
+        pckg = {"type_id": self._ids["@deep-foundation/core"]["Package"], "value": start} if isinstance(start, str) else {"id": start}
+        where = pckg
+        for item in path:
+            if not isinstance(item, bool):
+                nextWhere = {"in": {"type_id": self._ids["@deep-foundation/core"]["Contain"], "value": item, "from": where}}
+                where = nextWhere
+        return where
+
+    def serializeWhere(self, exp, env="links"):
+        if isinstance(exp, list):
+            return [self.serializeWhere(e, env) for e in exp]
+        elif isinstance(exp, dict):
+            result = {}
+            for key, value in exp.items():
+                setted = False
+                is_id_field = key in ["type_id", "from_id", "to_id"]
+                if env == "links":
+                    if isinstance(value, (str, int)):
+                        if key in ["value", str(value)]:
+                            setted = result[value] = {"_eq": value}
+                        else:
+                            setted = result[key] = {"_eq": value}
+                    elif key not in self._boolExpFields and isinstance(value, list):
+                        setted = result[key] = self.pathToWhere(*value)
+                elif env == "value":
+                    if isinstance(value, (str, int)):
+                        setted = result[key] = {"_eq": value}
+                # ... (continue conversion)
+            return result
+        elif exp is None:
+            raise ValueError("None in query")
+        else:
+            return exp
\ No newline at end of file


Test patch:
diff --git a/test_deep_client.py b/test_deep_client.py
new file mode 100644
index 0000000..5498872
--- /dev/null
+++ b/test_deep_client.py
@@ -0,0 +1,30 @@
+import unittest
+from deep_client import DeepClient
+
+
+class TestDeepClient(unittest.TestCase):
+
+    def setUp(self):
+        self.dc = DeepClient()
+
+    def test_serializeWhere(self):
+        query = {
+            "from_id": {"_type_of": "Package"},
+            "_and": [
+                {"to_id": {"_type_of": "Selector"}},
+                {"type_id": {"_type_of": "Contain"}}
+            ]
+        }
+        expected_result = {
+            "from_id": {"_by_item": {"path_item_id": {"_eq": "Package"}, "group_id": {"_eq": 0}}},
+            "_and": [
+                {"to_id": {"_by_item": {"path_item_id": {"_eq": "Selector"}, "group_id": {"_eq": 0}}}},
+                {"type_id": {"_by_item": {"path_item_id": {"_eq": "Contain"}, "group_id": {"_eq": 0}}}}
+            ]
+        }
+        serialized_query = self.dc.serializeWhere(query)
+        self.assertEqual(serialized_query, expected_result)
+
+
+if __name__ == '__main__':
+    unittest.main()
\ No newline at end of file