# imobject
`imobject` is a Python library that provides improvements for basic data types such as lists, dicts and dictionaries.
If you want to make data handling easier in Python, you can use imobject. It is a library that has three helpful classes: `ObjDict`, `ImprovedList` and `OrmCollection`.
# Features
The `imobject` library provides the following features:
The `ObjDict` class allows you to create dictionary objects (Dictionary-like object or Dynamic Class as dict), which makes it easier to access and manipulate data elements. This class inherits from the built-in `dict` class and adds features such as converting dictionaries to objects, handling missing keys and access dictionary keys as attributes.
The `ImprovedList` class offers an improved alternative to the Python list class, which it provide additional methods for working with lists of `ObjDict`. This class extends the built-in `list` class and adds features such as inspecting the elements of a list and performing advanced mapping operations.
The `OrmCollection` class providing an interface and additional methods for querying and manipulating objects in the `ImprovedList`. This class is a list-like collection that extends `ImprovedList` and that implements an ORM overlay (wrapper) for a list of `ObjDict`.
# Installation
You can install the imobject library using pip:
```pip install imobject```
# ontribute
If you want to contribute to the imobject library, you can clone the project from GitHub and submit a pull request:
`git clone https://github.com/username/imobject.git`
# Licence
The `imobject` library is distributed under the MIT license. See LICENSE for more information.
# Exemples [HERE](https://github.com/mzakariabigdata/imobject/tree/main/examples)
Here are some examples of using the imobject library.
## ObjDict
```python
>>> from imobject import ObjDict
>>> class Person:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def __repr__(self) -> str:
return f"Person(name='{self.name}', age={self.age})"
>>> person = Person("zakaria", 33)
>>> obj = ObjDict({"a": 1, "test": {"zak": person}, "b": {"c": 2, "d": [3, 4]}})
>>> obj.a
1
>>> obj.select(['a'])
{'a': 1}
>>> res = obj.select(['a', 'b'])
>>> res
{'a': 1, 'b': {'c': 2, 'd': [3, 4]}}
>>> type(res)
<class 'imobject.obj_dict.ObjDict'>
>>> obj.select(1)
TypeError: Argument 'wanted_keys' should be a list, got 'int' instead.
>>> obj.select("d")
TypeError: Argument 'wanted_keys' should be a list, got 'str' instead.
>>> obj.select(["c"])
KeyError: "'ObjDict' object has no attribute 'c'"
>>> res.b
{'c': 2, 'd': [3, 4]}
>>> obj.select(['a', 'test'])
{'a': 1, 'test': {'zak': Person(name='zakaria', age=33)}}
>>> obj.select(['c'])
KeyError: "'ObjDict' object has no attribute 'c'"
>>> obj.a = 13
>>> obj.a
13
>>> obj['b']['c']
2
>>> obj.b.c
2
>>> obj.x = {"y": 5}
>>> obj.x
{"y": 5}
>>> obj.inspect
{ 'a': 13,
'b': {'c': 2, 'd': [3, 4]},
'test': {'zak': Person(name='zakaria', age=33)},
'x': {'y': 5}}
>>> del obj.a
>>> obj.a
AttributeError: 'ObjDict' object has no attribute 'a'
>>> obj_dict = obj.to_dict()
>>> obj_dict
{'test': {'zak': Person(name='zakaria', age=33)}, 'b': {'c': 2, 'd': [3, 4]}, 'x': {'y': 5}}
>>> type(obj_dict)
<class 'dict'>
>>> obj = ObjDict({
"name": "Jane",
"age": 35,
"address": {"street": "456 Second St", "city": "Othertown", "state": "MA"},
"scores": [85, 95],
})
>>> obj
{'name': 'Jane', 'age': 35, 'address': {'street': '456 Second St', 'city': 'Othertown', 'state': 'MA'}, 'scores': [85, 95]}
>>> obj.update({
"name": "Will",
"age": 50,
"address": {"street": "456 Second St", "city": "Othertown", "state": "LA"},
"scores": [85, 100],
})
>>> obj
{'name': 'Will', 'age': 50, 'address': {'street': '456 Second St', 'city': 'Othertown', 'state': 'LA'}, 'scores': [85, 100]}
>>> obj.items()
[('name', 'Will'), ('age', 50), ('address', {'street': '456 Second St', 'city': 'Othertown', 'state': 'LA'}), ('scores', [85, 100])]
>>> copied_dict = obj.copy()
>>> copied_dict
{'name': 'Will', 'age': 50, 'address': {'street': '456 Second St', 'city': 'Othertown', 'state': 'LA'}, 'scores': [85, 100]}
```
## ImprovedList
```python
>>> from imobject import ImprovedList
>>> simple_list = ImprovedList([1, 2, 3])
>>> simple_list.first()
1
>>> simple_list.first(2)
[1, 2]
>>> ImprovedList([]).first() # None
>>> ImprovedList([1, 2, 3]).last()
3
>>> ImprovedList([1, 2, 3]).last(2)
[2, 3]
>>> ImprovedList([]).last() # None
>>> ImprovedList([1, 2, 3]).map(":__str__")
['1', '2', '3']
>>> ImprovedList([1, 2, 3]).map(str)
['1', '2', '3']
>>> ImprovedList([1, 2, 3]).map(":to_bytes")
[b'\x01', b'\x02', b'\x03']
>>> ImprovedList([1, 2, 3]).map(float)
[1.0, 2.0, 3.0]
>>> ImprovedList([1, 2, 3]).map(lambda x: x * 2)
[2, 4, 6]
>>> ImprovedList([1, 2, 3]).map(lambda x: x ** 2)
[1, 4, 9]
>>> ImprovedList([]).map(float)
[]
>>> class Person:
def __init__(self, name: str, age: int, salary: float, date: str):
self.name = name
self.age = age
self.salary = salary
self.date = datetime.strptime(date, "%Y-%m-%d")
@property
def ret_name(self) -> str:
return self.name
def get_name(self) -> str:
return self.name
def upper_name(self) -> str:
return self.name.upper()
def get_age(self) -> int:
return self.age
def change_name(self, new_name: str) -> None:
self.name = new_name
def change_age(self, new_age: int) -> None:
self.age = new_age
def is_adult(self) -> bool:
return self.age >= 18
def set_name(self, new_name: str) -> None:
self.name = new_name
def __repr__(self) -> str:
return f"Person(name='{self.name}', age={self.age}, salary={self.salary}, date={self.date})"
>>> from datetime import datetime
>>> people = [
Person("Alice", 25, 100, "2022-01-05"),
Person("Bob", 12, 364, "2021-12-25"),
Person("Charlie", 35, 740, "2022-01-20"),
]
>>> person_list = ImprovedList(people)
>>> person_list.map(':upper_name')
['ALICE', 'BOB', 'CHARLIE']
>>> person_list.map(":is_adult")
[True, False, True]
>>> person_list.map(":get_age")
[25, 12, 35]
>>> person_list.map(".name")
['Alice', 'Bob', 'Charlie']
>>> person_list.map(".age")
[25, 12, 35]
>>> person_list.map(lambda x: x.get_name(), filter_func=lambda x: isinstance(x, Person) and x.age >= 30)
['Charlie']
>>> person_list.map(":get_name", filter_func=lambda x: isinstance(x, Person))
['Alice', 'Bob', 'Charlie']
>>> person_list.map(".name", filter_func=lambda x: isinstance(x, Person))
['Alice', 'Bob', 'Charlie']
>>> person_list.map("name", filter_func=lambda x: isinstance(x, Person))
TypeError: called must be a string start with ':' for obj method or '.' obj attribute, or a callab
>>> def sort_by_date(obj: Person) -> datetime:
return obj.date
>>> person_list.map(called=lambda obj: obj.name, sort_func=sort_by_date)
['Bob', 'Alice', 'Charlie']
>>> person_list.map(called=lambda obj: obj, sort_func=sort_by_date)
[Person(name='Bob', age=12, salary=364, date=2021-12-25 00:00:00), Person(name='Alice', age=25, salary=100, date=2022-01-05 00:00:00), Person(name='Charlie', age=35, salary=740, date=2022-01-20 00:00:00)]
>>> data_list = person_list + ImprovedList([1,2,3,"four",5.0,{"six": 6},[7],"Apple","Banana","Orange"])
>>> data_list
[Person(name='Alice', age=25, salary=100, date=2022-01-05 00:00:00), Person(name='Bob', age=12, salary=364, date=2021-12-25 00:00:00), Person(name='Charlie', age=35, salary=740, date=2022-01-20 00:00:00), 1, 2, 3, 10, 'four', 5.0, {'six': 6}, [7], 'Apple', 'Banana', 'Orange']
>>> data_list.map(called=lambda x: x**2, filter_func=lambda x: isinstance(x, int) and x % 2 == 0)
[4, 100]
>>> data_list.map(called=lambda x: x.upper(), filter_func=lambda x: isinstance(x, str) and len(x) > 5)
['BANANA', 'ORANGE']
>>> data_list.map(called=lambda x: x.capitalize(), filter_func=lambda x: isinstance(x, str) and "a" in x.lower())
['Apple', 'Banana', 'Orange']
>>> data_list.map(called=str, filter_func=lambda x: isinstance(x, int) and x >= 3)
['3', '10']
>>> person_list.map(":change_name", **{"new_name": "Thor"})
[None, None, None]
>>> person_list.inspect
ImprovedList(Person) data:
Person(name='Thor', age=25, salary=100)
Person(name='Thor', age=12, salary=364)
Person(name='Thor', age=35, salary=740)
>>> person_list.map(":change_name", **{"new_name": ""})
[None, None, None]
>>> person_list.inspect
ImprovedList(Person) data:
Person(name='', age=25, salary=100)
Person(name='', age=12, salary=364)
Person(name='', age=35, salary=740)
```
## OrmCollection
```python
# Importer la classe OrmCollection
import re
from imobject import (
OrmCollection,
ObjDict,
Query,
Filter,
BaseMultipleFound,
BaseNotFound,
)
# Create an instance of the OrmCollection class with data
orm_collection = OrmCollection(
[
ObjDict(
{
"name": "Alice",
"age": 25,
"gender": "female",
"occupation": "psychologist",
}
),
ObjDict(
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"}
),
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
]
)
my_orm_collection_group = OrmCollection(
[
{"name": "Alice", "age": 25, "gender": "female", "occupation": "psy"},
{"name": "Alice", "age": 80, "gender": "male", "occupation": "retraite"},
{"name": "Bob", "age": 40, "gender": "male", "occupation": "cia"},
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "etud"},
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "prof"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "ing"},
{"name": "Dave", "age": 31, "gender": "male", "occupation": "prof"},
]
)
# Find all elements with name 'Alice'
results = orm_collection.where(name="Alice")
assert len(results) == 1
assert results[0] == {
"name": "Alice",
"age": 25,
"gender": "female",
"occupation": "psychologist",
}
# Find all elements where age is greater than 30 and occupation contains the word 'agent'
results = orm_collection.where(age__gt=30, occupation__contains="agent")
assert len(results) == 1
assert results[0] == {
"name": "Bob",
"age": 40,
"gender": "male",
"occupation": "CIA agent",
}
# Find all elements where age is not equal to 30
results = orm_collection.where(age__not=30)
assert len(results) == 2
assert results[0] == {
"name": "Alice",
"age": 25,
"gender": "female",
"occupation": "psychologist",
}
assert results[1] == {
"name": "Bob",
"age": 40,
"gender": "male",
"occupation": "CIA agent",
}
# Find all elements where name contains the letter 'a' and occupation starts with the letter 'p'
results = orm_collection.where(name__contains="c", occupation__startswith="p")
assert len(results) == 1
assert results[0] == {
"name": "Alice",
"age": 25,
"gender": "female",
"occupation": "psychologist",
}
# Trouver tous les éléments avec le nom commençant par "A" ou se terminant par "e"
results = orm_collection.where(name=re.compile(r"^A.*|.*e$"))
assert len(results) == 3
assert all(result["name"] in {"Alice", "Charlie", "Dave"} for result in results)
# Trouver tous les éléments avec le nom commençant par "A"
results = orm_collection.where(name=re.compile(r"^A.*"))
assert len(results) == 1
assert results[0]["name"] == "Alice"
# Trouver tous les éléments avec le nom se terminant par "e"
results = orm_collection.where(name=".*e$")
assert len(results) == 3
assert all(result["name"] in {"Alice", "Charlie", "Dave"} for result in results)
# Trouver tous les éléments avec un nom vide (devrait renvoyer tous les éléments)
results = orm_collection.where(name="")
print(results, len(results), len(orm_collection))
assert len(results) == len(orm_collection)
assert all(result in orm_collection for result in results)
# Trouver tous les éléments sans paramètres (devrait renvoyer 0 éléments)
results = orm_collection.where()
assert len(results) == 0
# Trouver tous les éléments avec l'âge égal à 100 (devrait renvoyer un ensemble vide)
results = orm_collection.where(age=100)
assert len(results) == 0
# Trouver tous les éléments avec le nom contenant la lettre "z"
results = orm_collection.where(name=re.compile(r".z.", re.IGNORECASE))
assert len(results) == 0
# Trouver tous les éléments avec le nom contenant la lettre "a" ou "e"
results = orm_collection.where(name=r"*a*|*e*")
# assert len(results) == 3
# assert all(result["name"] in {"Alice", "Charlie", "Dave"} for result in results)
# Trouver tous les éléments avec le nom se terminant par "ie"
results = orm_collection.where(name=re.compile(r".*ie$", re.IGNORECASE))
assert len(results) == 1
assert results[0]["name"] == "Charlie"
# Find all elements where age is greater than or equal to 30 and name contains 'v'
results = orm_collection.where(age__gte=30, name__contains="v")
assert len(results) == 1
assert results[0]["name"] == "Dave"
# Find all elements where age is not 25 and name contains 'v'
results = orm_collection.where(age__nin=[25], name__contains="v")
assert len(results) == 1
assert results[0]["name"] == "Dave"
# Find all elements where age is not 25 and name ends with 'e'
results = orm_collection.where(age__nin=[25], name__endswith="e")
assert len(results) == 2
assert {result["name"] for result in results} == {"Dave", "Charlie"}
# Find all elements with age equal to 25
results = orm_collection.where(age=25)
assert len(results) == 1
assert results[0]["name"] == "Alice"
# Find all elements with gender 'male' and age equal to 30
results = orm_collection.where(gender="male", age=30)
assert len(results) == 2
assert {result["name"] for result in results} == {"Charlie", "Dave"}
# Find all elements with name containing letter 'a'
results = orm_collection.where(name__contains="a")
assert len(results) == 2
assert {result["name"] for result in results} == {"Charlie", "Dave"}
# Find all elements where age is greater than 25 and name contains 'v'
results = orm_collection.where(age__gt=25, name__contains="v")
assert len(results) == 1
assert results[0]["name"] == "Dave"
# Find all elements where age is either 25 or 30 and name contains 'v'
results = orm_collection.where(age__in=[25, 30], name__contains="v")
assert len(results) == 1
assert results[0]["name"] == "Dave"
# Find all elements where age is less than 40 and name contains 'v'
results = orm_collection.where(age__lt=40, name__contains="v")
assert len(results) == 1
assert results[0]["name"] == "Dave"
# Find all elements where age is not 40 and name contains 'v'
results = orm_collection.where(age__not=40, name__contains="v")
assert len(results) == 1
assert results[0]["name"] == "Dave"
# Find all elements where age is equal to 40 and name contains 'b'
results = orm_collection.where(age__eq=40, name__contains="b")
assert len(results) == 1
assert results[0]["name"] == "Bob"
# Find all elements where age is less than or equal to 30 and name contains 'v'
results = orm_collection.where(age__lte=30, name__contains="v")
assert len(results) == 1
assert results[0]["name"] == "Dave"
# Test TypeError pour l'opérateur 'gt' avec une chaîne de caractères
try:
orm_collection.where(**{"age__gt": "25"})
except TypeError as error:
assert (
error.args[0]
== "Invalid type for value of '>' operator : expected int, found str"
)
# Test TypeError pour l'opérateur 'in' avec un int
try:
orm_collection.where(**{"age__in": 25})
except TypeError as error:
assert (
error.args[0]
== "Invalid type for value of 'in' operator : expected list, found int"
)
# Test TypeError pour l'opérateur 'contains' avec un int
try:
orm_collection.where(**{"age__contains": 25})
except TypeError as error:
assert str(error) == "'contains' lookup only works for string type fields"
# Test TypeError pour l'opérateur 'startswith' avec un int
try:
orm_collection.where(**{"age__startswith": 25})
except TypeError as error:
assert str(error) == "'startswith' lookup only works for string type fields"
# Test TypeError pour l'opérateur 'eq' avec une chaîne de caractères
try:
orm_collection.where(**{"age__eq": "25"})
except TypeError as error:
assert (
str(error) == "'==' operator only works for same type fields, found int and str"
)
# Test ValueError pour un opérateur invalide
try:
orm_collection.where(Query([Filter("age", "test_not_op", 30)]))
except ValueError as error:
assert str(error) == "'test_not_op' is not a valid operator"
# Recherche des éléments avec l'âge égal à 30
query = Query([Filter("age", None, 30)])
expected_names = {"Charlie", "Dave"}
results = orm_collection.where(query)
# Define query to find all elements with gender equal to male AND age equal to 30 with Query
query = Query([Filter("age", None, 30), Filter("gender", None, "male")])
results = orm_collection.where(query)
assert results == [
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
]
# Define query to find all elements with gender equal to male AND age equal to 30 with Query
query = Query([Filter("age", None, 30)]) & Query([Filter("age", None, 30)])
results = orm_collection.where(query)
assert results == [
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
]
# Define query to find all elements with gender equal to male OR age equal to 30 with Query
query = Query([Filter("age", None, 30)]) | Query([Filter("age", None, 40)])
results = orm_collection.where(query)
assert results == [
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"},
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
]
# Test ValueError pour un paramètre invalide
try:
orm_collection.where(**{"name__notValid": "i"})
except ValueError as error:
assert str(error) == "'notValid' is not a valid operator"
try:
orm_collection.find_by(name=".*a.*")
assert (
False
), "Le test a échoué, car plusieurs éléments ont été trouvés avec le nom contenant 'a'."
except BaseMultipleFound:
pass
try:
orm_collection.find_by(age=20)
assert (
False
), "Le test a échoué, car aucun élément n'a été trouvé avec l'âge égal à 20."
except BaseNotFound:
pass
# should return only one result
result = None
try:
result = orm_collection.find_by(name__contains="v")
except BaseMultipleFound:
assert (
False
), "Le test a échoué, car plusieurs éléments ont été trouvés avec le nom contenant 'v'."
except BaseNotFound:
assert (
False
), "Le test a échoué, car aucun élément n'a été trouvé avec le nom contenant 'v'."
assert result == {"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"}
# Group element by attributs
results = my_orm_collection_group.group_by(lambda x: x.age)
assert len(results) == 5
assert set(results.keys()) == {25, 30, 80, 31, 40}
results = my_orm_collection_group.group_by(lambda x: x.occupation)
assert len(results) == 6
assert set(results.keys()) == {"psy", "retraite", "cia", "etud", "ing", "prof"}
# Group element by two attributs
results = orm_collection.group_by(lambda x: (x.gender, x.age))
assert len(results) == 3
assert results == {
("female", 25): [
{"name": "Alice", "age": 25, "gender": "female", "occupation": "psychologist"}
],
("male", 40): [
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"}
],
("male", 30): [
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
],
}
assert set(results.keys()) == {
("female", 25),
("male", 40),
("male", 30),
}
# Créer une liste de noms
noms = ["Alice", "Bob", "Charlie", "David", "Edward"]
# Créer une collection ORM à partir de la liste
orm_collection_list = OrmCollection(noms)
# Grouper les noms par leur première lettre
results = orm_collection_list.group_by(lambda x: x[0])
# Vérifier les résultats attendus
assert results == {
"A": ["Alice"],
"B": ["Bob"],
"C": ["Charlie"],
"D": ["David"],
"E": ["Edward"],
}
# Créer une liste de nombres
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Créer une collection ORM à partir de la liste
orm_collection_list = OrmCollection(nombres)
# Grouper les nombres pairs et impairs
results = orm_collection_list.group_by(lambda x: x % 2 == 0)
assert results == {True: [2, 4, 6, 8, 10], False: [1, 3, 5, 7, 9]}
# Trier une liste d'objets de la plus jeune à la plus âgée
people = [
{"name": "Alice", "age": 25, "gender": "female"},
{"name": "Bob", "age": 40, "gender": "male"},
{"name": "Charlie", "age": 30, "gender": "male"},
{"name": "Dave", "age": 30, "gender": "male"},
]
ordered_people = orm_collection.order_by("age")
assert ordered_people == [
{"name": "Alice", "age": 25, "gender": "female", "occupation": "psychologist"},
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"},
]
# Trier une liste d'objets par ordre alphabétique de leur nom :
people = [
{"name": "Alice", "age": 25, "gender": "female"},
{"name": "Bob", "age": 40, "gender": "male"},
{"name": "Charlie", "age": 30, "gender": "male"},
{"name": "Dave", "age": 30, "gender": "male"},
]
ordered_people = orm_collection.order_by(lambda x: x["name"])
assert ordered_people == [
{"name": "Alice", "age": 25, "gender": "female", "occupation": "psychologist"},
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"},
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
]
# Trier la liste par ordre alphabétique
lst = OrmCollection(["apple", "banana", "orange", "f", "pear", "c'est encore moi"])
ordered_lst = lst.order_by()
assert ordered_lst == ["f", "pear", "apple", "banana", "orange", "c'est encore moi"]
# Trier la liste
lst = OrmCollection([4, 2, 1, 3])
ordered_lst = lst.order_by()
assert ordered_lst == [1, 2, 3, 4]
# Lancer une erreur pour une clé de tri invalide
try:
orm_collection.order_by(123)
except TypeError:
pass
try:
orm_collection.order_by(None)
except ValueError:
pass
# Tri d'une liste d'objets par l'âge décroissant
ordered_lst = orm_collection.order_by(lambda x: -x["age"])
assert ordered_lst == [
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"},
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
{"name": "Alice", "age": 25, "gender": "female", "occupation": "psychologist"},
]
# Tri d'une liste d'objets par l'âge décroissant
results = OrmCollection([4, 2, 1, 3]).order_by(lambda x: -x)
# Vérifier les résultats attendus
assert results == [4, 3, 2, 1]
# Utiliser la méthode all() pour récupérer tous les éléments
all_elements = orm_collection.all()
assert all_elements == [
{"name": "Alice", "age": 25, "gender": "female", "occupation": "psychologist"},
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"},
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
]
# Utiliser la méthode offset() pour récupérer les éléments à partir de l'index 2
offset_elements = orm_collection.offset(2)
assert offset_elements == [
{"name": "Charlie", "age": 30, "gender": "male", "occupation": "student"},
{"name": "Dave", "age": 30, "gender": "male", "occupation": "engineer"},
]
# Utiliser la méthode limit() pour récupérer les deux premiers éléments
limit_elements = orm_collection.limit(2)
assert limit_elements == [
{"name": "Alice", "age": 25, "gender": "female", "occupation": "psychologist"},
{"name": "Bob", "age": 40, "gender": "male", "occupation": "CIA agent"},
]
lst = OrmCollection([1, 2, 3, 4])
distinct_lst = lst.distinct()
assert distinct_lst == [1, 2, 3, 4]
lst = OrmCollection([1, 2, 2, 3, 4, 4])
distinct_lst = lst.distinct()
assert distinct_lst == [1, 2, 3, 4]
lst = OrmCollection(["apple", "banana", "orange", "f", "pear", "orange"])
distinct_lst = lst.distinct()
assert distinct_lst == ["apple", "banana", "orange", "f", "pear"]
orm_collection = OrmCollection(
[
{"name": "Alice", "age": 25, "gender": "female", "taf": "psy"},
{"name": "Alice", "age": 80, "gender": "male", "taf": "retraite"},
{"name": "Bob", "age": 40, "gender": "male", "taf": "cia"},
{"name": "Charlie", "age": 30, "gender": "male", "taf": "etud"},
{"name": "Charlie", "age": 30, "gender": "male", "taf": "prof"},
{"name": "Dave", "age": 30, "gender": "male", "taf": "ing"},
{"name": "Dave", "age": 31, "gender": "male", "taf": "chomor"},
]
)
distinct_coll = orm_collection.distinct("name", "age")
assert len(distinct_coll) == 6
assert {(person["name"], person["age"]) for person in distinct_coll} == {
("Alice", 25),
("Alice", 80),
("Dave", 30),
("Dave", 31),
("Bob", 40),
("Charlie", 30),
}
```
Raw data
{
"_id": null,
"home_page": "https://github.com/mzakariabigdata/imobject",
"name": "imobject",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": "",
"author": "Zakaria Morchid",
"author_email": "morchid.zakariaa@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/1b/26/55a8f80e80657e476ec0f41c637e41caab21be2bbf8df2cab0ba1708e727/imobject-2.0.1.tar.gz",
"platform": null,
"description": "# imobject\r\n\r\n`imobject` is a Python library that provides improvements for basic data types such as lists, dicts and dictionaries.\r\n\r\nIf you want to make data handling easier in Python, you can use imobject. It is a library that has three helpful classes: `ObjDict`, `ImprovedList` and `OrmCollection`.\r\n\r\n# Features\r\n\r\nThe `imobject` library provides the following features:\r\n\r\nThe `ObjDict` class allows you to create dictionary objects (Dictionary-like object or Dynamic Class as dict), which makes it easier to access and manipulate data elements. This class inherits from the built-in `dict` class and adds features such as converting dictionaries to objects, handling missing keys and access dictionary keys as attributes.\r\n\r\nThe `ImprovedList` class offers an improved alternative to the Python list class, which it provide additional methods for working with lists of `ObjDict`. This class extends the built-in `list` class and adds features such as inspecting the elements of a list and performing advanced mapping operations.\r\n\r\nThe `OrmCollection` class providing an interface and additional methods for querying and manipulating objects in the `ImprovedList`. This class is a list-like collection that extends `ImprovedList` and that implements an ORM overlay (wrapper) for a list of `ObjDict`.\r\n\r\n# Installation\r\nYou can install the imobject library using pip:\r\n\r\n```pip install imobject```\r\n\r\n# ontribute\r\nIf you want to contribute to the imobject library, you can clone the project from GitHub and submit a pull request:\r\n\r\n`git clone https://github.com/username/imobject.git`\r\n\r\n# Licence\r\n\r\nThe `imobject` library is distributed under the MIT license. See LICENSE for more information.\r\n\r\n# Exemples [HERE](https://github.com/mzakariabigdata/imobject/tree/main/examples)\r\n\r\nHere are some examples of using the imobject library.\r\n\r\n## ObjDict\r\n```python\r\n>>> from imobject import ObjDict\r\n>>> class Person:\r\n def __init__(self, name: str, age: int) -> None:\r\n self.name = name\r\n self.age = age\r\n def __repr__(self) -> str:\r\n return f\"Person(name='{self.name}', age={self.age})\"\r\n\r\n>>> person = Person(\"zakaria\", 33)\r\n>>> obj = ObjDict({\"a\": 1, \"test\": {\"zak\": person}, \"b\": {\"c\": 2, \"d\": [3, 4]}})\r\n>>> obj.a\r\n1\r\n>>> obj.select(['a'])\r\n{'a': 1}\r\n>>> res = obj.select(['a', 'b'])\r\n>>> res\r\n{'a': 1, 'b': {'c': 2, 'd': [3, 4]}}\r\n>>> type(res)\r\n<class 'imobject.obj_dict.ObjDict'>\r\n>>> obj.select(1)\r\nTypeError: Argument 'wanted_keys' should be a list, got 'int' instead.\r\n>>> obj.select(\"d\")\r\nTypeError: Argument 'wanted_keys' should be a list, got 'str' instead.\r\n>>> obj.select([\"c\"])\r\nKeyError: \"'ObjDict' object has no attribute 'c'\"\r\n>>> res.b\r\n{'c': 2, 'd': [3, 4]}\r\n>>> obj.select(['a', 'test'])\r\n{'a': 1, 'test': {'zak': Person(name='zakaria', age=33)}}\r\n>>> obj.select(['c'])\r\nKeyError: \"'ObjDict' object has no attribute 'c'\"\r\n>>> obj.a = 13\r\n>>> obj.a\r\n13\r\n>>> obj['b']['c']\r\n2\r\n>>> obj.b.c\r\n2\r\n>>> obj.x = {\"y\": 5}\r\n>>> obj.x\r\n{\"y\": 5}\r\n>>> obj.inspect\r\n{ 'a': 13,\r\n 'b': {'c': 2, 'd': [3, 4]},\r\n 'test': {'zak': Person(name='zakaria', age=33)},\r\n 'x': {'y': 5}}\r\n>>> del obj.a\r\n>>> obj.a\r\nAttributeError: 'ObjDict' object has no attribute 'a'\r\n>>> obj_dict = obj.to_dict()\r\n>>> obj_dict\r\n{'test': {'zak': Person(name='zakaria', age=33)}, 'b': {'c': 2, 'd': [3, 4]}, 'x': {'y': 5}}\r\n>>> type(obj_dict)\r\n<class 'dict'>\r\n>>> obj = ObjDict({\r\n \"name\": \"Jane\",\r\n \"age\": 35,\r\n \"address\": {\"street\": \"456 Second St\", \"city\": \"Othertown\", \"state\": \"MA\"},\r\n \"scores\": [85, 95],\r\n })\r\n>>> obj\r\n{'name': 'Jane', 'age': 35, 'address': {'street': '456 Second St', 'city': 'Othertown', 'state': 'MA'}, 'scores': [85, 95]}\r\n>>> obj.update({\r\n \"name\": \"Will\",\r\n \"age\": 50,\r\n \"address\": {\"street\": \"456 Second St\", \"city\": \"Othertown\", \"state\": \"LA\"},\r\n \"scores\": [85, 100],\r\n })\r\n>>> obj\r\n{'name': 'Will', 'age': 50, 'address': {'street': '456 Second St', 'city': 'Othertown', 'state': 'LA'}, 'scores': [85, 100]}\r\n>>> obj.items()\r\n[('name', 'Will'), ('age', 50), ('address', {'street': '456 Second St', 'city': 'Othertown', 'state': 'LA'}), ('scores', [85, 100])]\r\n>>> copied_dict = obj.copy()\r\n>>> copied_dict\r\n{'name': 'Will', 'age': 50, 'address': {'street': '456 Second St', 'city': 'Othertown', 'state': 'LA'}, 'scores': [85, 100]}\r\n```\r\n## ImprovedList\r\n```python\r\n>>> from imobject import ImprovedList\r\n>>> simple_list = ImprovedList([1, 2, 3])\r\n>>> simple_list.first()\r\n1\r\n>>> simple_list.first(2)\r\n[1, 2]\r\n>>> ImprovedList([]).first() # None\r\n>>> ImprovedList([1, 2, 3]).last()\r\n3\r\n>>> ImprovedList([1, 2, 3]).last(2)\r\n[2, 3]\r\n>>> ImprovedList([]).last() # None\r\n>>> ImprovedList([1, 2, 3]).map(\":__str__\")\r\n['1', '2', '3']\r\n>>> ImprovedList([1, 2, 3]).map(str)\r\n['1', '2', '3']\r\n>>> ImprovedList([1, 2, 3]).map(\":to_bytes\")\r\n[b'\\x01', b'\\x02', b'\\x03']\r\n>>> ImprovedList([1, 2, 3]).map(float)\r\n[1.0, 2.0, 3.0]\r\n>>> ImprovedList([1, 2, 3]).map(lambda x: x * 2)\r\n[2, 4, 6]\r\n>>> ImprovedList([1, 2, 3]).map(lambda x: x ** 2)\r\n[1, 4, 9]\r\n>>> ImprovedList([]).map(float)\r\n[]\r\n>>> class Person:\r\n def __init__(self, name: str, age: int, salary: float, date: str):\r\n self.name = name\r\n self.age = age\r\n self.salary = salary\r\n self.date = datetime.strptime(date, \"%Y-%m-%d\")\r\n @property\r\n def ret_name(self) -> str:\r\n return self.name\r\n def get_name(self) -> str:\r\n return self.name\r\n def upper_name(self) -> str:\r\n return self.name.upper()\r\n def get_age(self) -> int:\r\n return self.age\r\n def change_name(self, new_name: str) -> None:\r\n self.name = new_name\r\n def change_age(self, new_age: int) -> None:\r\n self.age = new_age\r\n def is_adult(self) -> bool:\r\n return self.age >= 18\r\n def set_name(self, new_name: str) -> None:\r\n self.name = new_name\r\n def __repr__(self) -> str:\r\n return f\"Person(name='{self.name}', age={self.age}, salary={self.salary}, date={self.date})\"\r\n>>> from datetime import datetime\r\n>>> people = [\r\n Person(\"Alice\", 25, 100, \"2022-01-05\"),\r\n Person(\"Bob\", 12, 364, \"2021-12-25\"),\r\n Person(\"Charlie\", 35, 740, \"2022-01-20\"),\r\n ]\r\n>>> person_list = ImprovedList(people)\r\n>>> person_list.map(':upper_name')\r\n['ALICE', 'BOB', 'CHARLIE']\r\n>>> person_list.map(\":is_adult\")\r\n[True, False, True]\r\n>>> person_list.map(\":get_age\")\r\n[25, 12, 35]\r\n>>> person_list.map(\".name\")\r\n['Alice', 'Bob', 'Charlie']\r\n>>> person_list.map(\".age\")\r\n[25, 12, 35]\r\n>>> person_list.map(lambda x: x.get_name(), filter_func=lambda x: isinstance(x, Person) and x.age >= 30)\r\n['Charlie']\r\n>>> person_list.map(\":get_name\", filter_func=lambda x: isinstance(x, Person))\r\n['Alice', 'Bob', 'Charlie']\r\n>>> person_list.map(\".name\", filter_func=lambda x: isinstance(x, Person))\r\n['Alice', 'Bob', 'Charlie']\r\n>>> person_list.map(\"name\", filter_func=lambda x: isinstance(x, Person))\r\nTypeError: called must be a string start with ':' for obj method or '.' obj attribute, or a callab\r\n>>> def sort_by_date(obj: Person) -> datetime:\r\n return obj.date\r\n>>> person_list.map(called=lambda obj: obj.name, sort_func=sort_by_date)\r\n['Bob', 'Alice', 'Charlie']\r\n>>> person_list.map(called=lambda obj: obj, sort_func=sort_by_date)\r\n[Person(name='Bob', age=12, salary=364, date=2021-12-25 00:00:00), Person(name='Alice', age=25, salary=100, date=2022-01-05 00:00:00), Person(name='Charlie', age=35, salary=740, date=2022-01-20 00:00:00)]\r\n>>> data_list = person_list + ImprovedList([1,2,3,\"four\",5.0,{\"six\": 6},[7],\"Apple\",\"Banana\",\"Orange\"])\r\n>>> data_list\r\n[Person(name='Alice', age=25, salary=100, date=2022-01-05 00:00:00), Person(name='Bob', age=12, salary=364, date=2021-12-25 00:00:00), Person(name='Charlie', age=35, salary=740, date=2022-01-20 00:00:00), 1, 2, 3, 10, 'four', 5.0, {'six': 6}, [7], 'Apple', 'Banana', 'Orange']\r\n>>> data_list.map(called=lambda x: x**2, filter_func=lambda x: isinstance(x, int) and x % 2 == 0)\r\n[4, 100]\r\n>>> data_list.map(called=lambda x: x.upper(), filter_func=lambda x: isinstance(x, str) and len(x) > 5)\r\n['BANANA', 'ORANGE']\r\n>>> data_list.map(called=lambda x: x.capitalize(), filter_func=lambda x: isinstance(x, str) and \"a\" in x.lower())\r\n['Apple', 'Banana', 'Orange']\r\n>>> data_list.map(called=str, filter_func=lambda x: isinstance(x, int) and x >= 3)\r\n['3', '10']\r\n>>> person_list.map(\":change_name\", **{\"new_name\": \"Thor\"})\r\n[None, None, None]\r\n>>> person_list.inspect\r\nImprovedList(Person) data:\r\nPerson(name='Thor', age=25, salary=100)\r\nPerson(name='Thor', age=12, salary=364)\r\nPerson(name='Thor', age=35, salary=740)\r\n>>> person_list.map(\":change_name\", **{\"new_name\": \"\"})\r\n[None, None, None]\r\n>>> person_list.inspect\r\nImprovedList(Person) data:\r\nPerson(name='', age=25, salary=100)\r\nPerson(name='', age=12, salary=364)\r\nPerson(name='', age=35, salary=740)\r\n```\r\n## OrmCollection\r\n```python\r\n# Importer la classe OrmCollection\r\nimport re\r\nfrom imobject import (\r\n OrmCollection,\r\n ObjDict,\r\n Query,\r\n Filter,\r\n BaseMultipleFound,\r\n BaseNotFound,\r\n)\r\n\r\n# Create an instance of the OrmCollection class with data\r\norm_collection = OrmCollection(\r\n [\r\n ObjDict(\r\n {\r\n \"name\": \"Alice\",\r\n \"age\": 25,\r\n \"gender\": \"female\",\r\n \"occupation\": \"psychologist\",\r\n }\r\n ),\r\n ObjDict(\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"}\r\n ),\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n ]\r\n)\r\n\r\nmy_orm_collection_group = OrmCollection(\r\n [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"occupation\": \"psy\"},\r\n {\"name\": \"Alice\", \"age\": 80, \"gender\": \"male\", \"occupation\": \"retraite\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"cia\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"etud\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"prof\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"ing\"},\r\n {\"name\": \"Dave\", \"age\": 31, \"gender\": \"male\", \"occupation\": \"prof\"},\r\n ]\r\n)\r\n\r\n# Find all elements with name 'Alice'\r\nresults = orm_collection.where(name=\"Alice\")\r\nassert len(results) == 1\r\nassert results[0] == {\r\n \"name\": \"Alice\",\r\n \"age\": 25,\r\n \"gender\": \"female\",\r\n \"occupation\": \"psychologist\",\r\n}\r\n\r\n# Find all elements where age is greater than 30 and occupation contains the word 'agent'\r\nresults = orm_collection.where(age__gt=30, occupation__contains=\"agent\")\r\nassert len(results) == 1\r\nassert results[0] == {\r\n \"name\": \"Bob\",\r\n \"age\": 40,\r\n \"gender\": \"male\",\r\n \"occupation\": \"CIA agent\",\r\n}\r\n\r\n# Find all elements where age is not equal to 30\r\nresults = orm_collection.where(age__not=30)\r\nassert len(results) == 2\r\nassert results[0] == {\r\n \"name\": \"Alice\",\r\n \"age\": 25,\r\n \"gender\": \"female\",\r\n \"occupation\": \"psychologist\",\r\n}\r\nassert results[1] == {\r\n \"name\": \"Bob\",\r\n \"age\": 40,\r\n \"gender\": \"male\",\r\n \"occupation\": \"CIA agent\",\r\n}\r\n\r\n# Find all elements where name contains the letter 'a' and occupation starts with the letter 'p'\r\nresults = orm_collection.where(name__contains=\"c\", occupation__startswith=\"p\")\r\nassert len(results) == 1\r\nassert results[0] == {\r\n \"name\": \"Alice\",\r\n \"age\": 25,\r\n \"gender\": \"female\",\r\n \"occupation\": \"psychologist\",\r\n}\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec le nom commen\u00e7ant par \"A\" ou se terminant par \"e\"\r\nresults = orm_collection.where(name=re.compile(r\"^A.*|.*e$\"))\r\nassert len(results) == 3\r\nassert all(result[\"name\"] in {\"Alice\", \"Charlie\", \"Dave\"} for result in results)\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec le nom commen\u00e7ant par \"A\"\r\nresults = orm_collection.where(name=re.compile(r\"^A.*\"))\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Alice\"\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec le nom se terminant par \"e\"\r\nresults = orm_collection.where(name=\".*e$\")\r\nassert len(results) == 3\r\nassert all(result[\"name\"] in {\"Alice\", \"Charlie\", \"Dave\"} for result in results)\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec un nom vide (devrait renvoyer tous les \u00e9l\u00e9ments)\r\nresults = orm_collection.where(name=\"\")\r\nprint(results, len(results), len(orm_collection))\r\nassert len(results) == len(orm_collection)\r\nassert all(result in orm_collection for result in results)\r\n\r\n# Trouver tous les \u00e9l\u00e9ments sans param\u00e8tres (devrait renvoyer 0 \u00e9l\u00e9ments)\r\nresults = orm_collection.where()\r\nassert len(results) == 0\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec l'\u00e2ge \u00e9gal \u00e0 100 (devrait renvoyer un ensemble vide)\r\nresults = orm_collection.where(age=100)\r\nassert len(results) == 0\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec le nom contenant la lettre \"z\"\r\nresults = orm_collection.where(name=re.compile(r\".z.\", re.IGNORECASE))\r\nassert len(results) == 0\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec le nom contenant la lettre \"a\" ou \"e\"\r\nresults = orm_collection.where(name=r\"*a*|*e*\")\r\n# assert len(results) == 3\r\n# assert all(result[\"name\"] in {\"Alice\", \"Charlie\", \"Dave\"} for result in results)\r\n\r\n# Trouver tous les \u00e9l\u00e9ments avec le nom se terminant par \"ie\"\r\nresults = orm_collection.where(name=re.compile(r\".*ie$\", re.IGNORECASE))\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Charlie\"\r\n\r\n# Find all elements where age is greater than or equal to 30 and name contains 'v'\r\nresults = orm_collection.where(age__gte=30, name__contains=\"v\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Dave\"\r\n\r\n# Find all elements where age is not 25 and name contains 'v'\r\nresults = orm_collection.where(age__nin=[25], name__contains=\"v\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Dave\"\r\n\r\n# Find all elements where age is not 25 and name ends with 'e'\r\nresults = orm_collection.where(age__nin=[25], name__endswith=\"e\")\r\nassert len(results) == 2\r\nassert {result[\"name\"] for result in results} == {\"Dave\", \"Charlie\"}\r\n\r\n# Find all elements with age equal to 25\r\nresults = orm_collection.where(age=25)\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Alice\"\r\n\r\n# Find all elements with gender 'male' and age equal to 30\r\nresults = orm_collection.where(gender=\"male\", age=30)\r\nassert len(results) == 2\r\nassert {result[\"name\"] for result in results} == {\"Charlie\", \"Dave\"}\r\n\r\n# Find all elements with name containing letter 'a'\r\nresults = orm_collection.where(name__contains=\"a\")\r\nassert len(results) == 2\r\nassert {result[\"name\"] for result in results} == {\"Charlie\", \"Dave\"}\r\n\r\n# Find all elements where age is greater than 25 and name contains 'v'\r\nresults = orm_collection.where(age__gt=25, name__contains=\"v\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Dave\"\r\n\r\n# Find all elements where age is either 25 or 30 and name contains 'v'\r\nresults = orm_collection.where(age__in=[25, 30], name__contains=\"v\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Dave\"\r\n\r\n# Find all elements where age is less than 40 and name contains 'v'\r\nresults = orm_collection.where(age__lt=40, name__contains=\"v\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Dave\"\r\n\r\n# Find all elements where age is not 40 and name contains 'v'\r\nresults = orm_collection.where(age__not=40, name__contains=\"v\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Dave\"\r\n\r\n# Find all elements where age is equal to 40 and name contains 'b'\r\nresults = orm_collection.where(age__eq=40, name__contains=\"b\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Bob\"\r\n\r\n# Find all elements where age is less than or equal to 30 and name contains 'v'\r\nresults = orm_collection.where(age__lte=30, name__contains=\"v\")\r\nassert len(results) == 1\r\nassert results[0][\"name\"] == \"Dave\"\r\n\r\n# Test TypeError pour l'op\u00e9rateur 'gt' avec une cha\u00eene de caract\u00e8res\r\ntry:\r\n orm_collection.where(**{\"age__gt\": \"25\"})\r\nexcept TypeError as error:\r\n assert (\r\n error.args[0]\r\n == \"Invalid type for value of '>' operator : expected int, found str\"\r\n )\r\n\r\n# Test TypeError pour l'op\u00e9rateur 'in' avec un int\r\ntry:\r\n orm_collection.where(**{\"age__in\": 25})\r\nexcept TypeError as error:\r\n assert (\r\n error.args[0]\r\n == \"Invalid type for value of 'in' operator : expected list, found int\"\r\n )\r\n\r\n# Test TypeError pour l'op\u00e9rateur 'contains' avec un int\r\ntry:\r\n orm_collection.where(**{\"age__contains\": 25})\r\nexcept TypeError as error:\r\n assert str(error) == \"'contains' lookup only works for string type fields\"\r\n\r\n# Test TypeError pour l'op\u00e9rateur 'startswith' avec un int\r\ntry:\r\n orm_collection.where(**{\"age__startswith\": 25})\r\nexcept TypeError as error:\r\n assert str(error) == \"'startswith' lookup only works for string type fields\"\r\n\r\n# Test TypeError pour l'op\u00e9rateur 'eq' avec une cha\u00eene de caract\u00e8res\r\ntry:\r\n orm_collection.where(**{\"age__eq\": \"25\"})\r\nexcept TypeError as error:\r\n assert (\r\n str(error) == \"'==' operator only works for same type fields, found int and str\"\r\n )\r\n\r\n# Test ValueError pour un op\u00e9rateur invalide\r\ntry:\r\n orm_collection.where(Query([Filter(\"age\", \"test_not_op\", 30)]))\r\nexcept ValueError as error:\r\n assert str(error) == \"'test_not_op' is not a valid operator\"\r\n\r\n# Recherche des \u00e9l\u00e9ments avec l'\u00e2ge \u00e9gal \u00e0 30\r\nquery = Query([Filter(\"age\", None, 30)])\r\nexpected_names = {\"Charlie\", \"Dave\"}\r\nresults = orm_collection.where(query)\r\n\r\n# Define query to find all elements with gender equal to male AND age equal to 30 with Query\r\nquery = Query([Filter(\"age\", None, 30), Filter(\"gender\", None, \"male\")])\r\nresults = orm_collection.where(query)\r\nassert results == [\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n]\r\n\r\n# Define query to find all elements with gender equal to male AND age equal to 30 with Query\r\nquery = Query([Filter(\"age\", None, 30)]) & Query([Filter(\"age\", None, 30)])\r\nresults = orm_collection.where(query)\r\nassert results == [\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n]\r\n\r\n# Define query to find all elements with gender equal to male OR age equal to 30 with Query\r\nquery = Query([Filter(\"age\", None, 30)]) | Query([Filter(\"age\", None, 40)])\r\nresults = orm_collection.where(query)\r\nassert results == [\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n]\r\n\r\n# Test ValueError pour un param\u00e8tre invalide\r\ntry:\r\n orm_collection.where(**{\"name__notValid\": \"i\"})\r\nexcept ValueError as error:\r\n assert str(error) == \"'notValid' is not a valid operator\"\r\n\r\ntry:\r\n orm_collection.find_by(name=\".*a.*\")\r\n assert (\r\n False\r\n ), \"Le test a \u00e9chou\u00e9, car plusieurs \u00e9l\u00e9ments ont \u00e9t\u00e9 trouv\u00e9s avec le nom contenant 'a'.\"\r\nexcept BaseMultipleFound:\r\n pass\r\n\r\ntry:\r\n orm_collection.find_by(age=20)\r\n assert (\r\n False\r\n ), \"Le test a \u00e9chou\u00e9, car aucun \u00e9l\u00e9ment n'a \u00e9t\u00e9 trouv\u00e9 avec l'\u00e2ge \u00e9gal \u00e0 20.\"\r\nexcept BaseNotFound:\r\n pass\r\n\r\n# should return only one result\r\nresult = None\r\ntry:\r\n result = orm_collection.find_by(name__contains=\"v\")\r\nexcept BaseMultipleFound:\r\n assert (\r\n False\r\n ), \"Le test a \u00e9chou\u00e9, car plusieurs \u00e9l\u00e9ments ont \u00e9t\u00e9 trouv\u00e9s avec le nom contenant 'v'.\"\r\nexcept BaseNotFound:\r\n assert (\r\n False\r\n ), \"Le test a \u00e9chou\u00e9, car aucun \u00e9l\u00e9ment n'a \u00e9t\u00e9 trouv\u00e9 avec le nom contenant 'v'.\"\r\nassert result == {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"}\r\n\r\n# Group element by attributs\r\nresults = my_orm_collection_group.group_by(lambda x: x.age)\r\nassert len(results) == 5\r\nassert set(results.keys()) == {25, 30, 80, 31, 40}\r\n\r\nresults = my_orm_collection_group.group_by(lambda x: x.occupation)\r\nassert len(results) == 6\r\nassert set(results.keys()) == {\"psy\", \"retraite\", \"cia\", \"etud\", \"ing\", \"prof\"}\r\n\r\n# Group element by two attributs\r\nresults = orm_collection.group_by(lambda x: (x.gender, x.age))\r\nassert len(results) == 3\r\nassert results == {\r\n (\"female\", 25): [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"occupation\": \"psychologist\"}\r\n ],\r\n (\"male\", 40): [\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"}\r\n ],\r\n (\"male\", 30): [\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n ],\r\n}\r\nassert set(results.keys()) == {\r\n (\"female\", 25),\r\n (\"male\", 40),\r\n (\"male\", 30),\r\n}\r\n\r\n# Cr\u00e9er une liste de noms\r\nnoms = [\"Alice\", \"Bob\", \"Charlie\", \"David\", \"Edward\"]\r\n\r\n# Cr\u00e9er une collection ORM \u00e0 partir de la liste\r\norm_collection_list = OrmCollection(noms)\r\n\r\n# Grouper les noms par leur premi\u00e8re lettre\r\nresults = orm_collection_list.group_by(lambda x: x[0])\r\n\r\n# V\u00e9rifier les r\u00e9sultats attendus\r\nassert results == {\r\n \"A\": [\"Alice\"],\r\n \"B\": [\"Bob\"],\r\n \"C\": [\"Charlie\"],\r\n \"D\": [\"David\"],\r\n \"E\": [\"Edward\"],\r\n}\r\n\r\n# Cr\u00e9er une liste de nombres\r\nnombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]\r\n\r\n# Cr\u00e9er une collection ORM \u00e0 partir de la liste\r\norm_collection_list = OrmCollection(nombres)\r\n\r\n# Grouper les nombres pairs et impairs\r\nresults = orm_collection_list.group_by(lambda x: x % 2 == 0)\r\nassert results == {True: [2, 4, 6, 8, 10], False: [1, 3, 5, 7, 9]}\r\n\r\n\r\n# Trier une liste d'objets de la plus jeune \u00e0 la plus \u00e2g\u00e9e\r\npeople = [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\"},\r\n]\r\nordered_people = orm_collection.order_by(\"age\")\r\nassert ordered_people == [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"occupation\": \"psychologist\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"},\r\n]\r\n\r\n# Trier une liste d'objets par ordre alphab\u00e9tique de leur nom :\r\npeople = [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\"},\r\n]\r\nordered_people = orm_collection.order_by(lambda x: x[\"name\"])\r\nassert ordered_people == [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"occupation\": \"psychologist\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n]\r\n\r\n# Trier la liste par ordre alphab\u00e9tique\r\nlst = OrmCollection([\"apple\", \"banana\", \"orange\", \"f\", \"pear\", \"c'est encore moi\"])\r\nordered_lst = lst.order_by()\r\nassert ordered_lst == [\"f\", \"pear\", \"apple\", \"banana\", \"orange\", \"c'est encore moi\"]\r\n\r\n# Trier la liste\r\nlst = OrmCollection([4, 2, 1, 3])\r\nordered_lst = lst.order_by()\r\nassert ordered_lst == [1, 2, 3, 4]\r\n\r\n\r\n# Lancer une erreur pour une cl\u00e9 de tri invalide\r\ntry:\r\n orm_collection.order_by(123)\r\nexcept TypeError:\r\n pass\r\n\r\ntry:\r\n orm_collection.order_by(None)\r\nexcept ValueError:\r\n pass\r\n\r\n# Tri d'une liste d'objets par l'\u00e2ge d\u00e9croissant\r\nordered_lst = orm_collection.order_by(lambda x: -x[\"age\"])\r\nassert ordered_lst == [\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"occupation\": \"psychologist\"},\r\n]\r\n# Tri d'une liste d'objets par l'\u00e2ge d\u00e9croissant\r\nresults = OrmCollection([4, 2, 1, 3]).order_by(lambda x: -x)\r\n# V\u00e9rifier les r\u00e9sultats attendus\r\nassert results == [4, 3, 2, 1]\r\n\r\n\r\n# Utiliser la m\u00e9thode all() pour r\u00e9cup\u00e9rer tous les \u00e9l\u00e9ments\r\nall_elements = orm_collection.all()\r\nassert all_elements == [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"occupation\": \"psychologist\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n]\r\n\r\n# Utiliser la m\u00e9thode offset() pour r\u00e9cup\u00e9rer les \u00e9l\u00e9ments \u00e0 partir de l'index 2\r\noffset_elements = orm_collection.offset(2)\r\nassert offset_elements == [\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"student\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"occupation\": \"engineer\"},\r\n]\r\n\r\n# Utiliser la m\u00e9thode limit() pour r\u00e9cup\u00e9rer les deux premiers \u00e9l\u00e9ments\r\nlimit_elements = orm_collection.limit(2)\r\nassert limit_elements == [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"occupation\": \"psychologist\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"occupation\": \"CIA agent\"},\r\n]\r\n\r\nlst = OrmCollection([1, 2, 3, 4])\r\ndistinct_lst = lst.distinct()\r\nassert distinct_lst == [1, 2, 3, 4]\r\n\r\nlst = OrmCollection([1, 2, 2, 3, 4, 4])\r\ndistinct_lst = lst.distinct()\r\nassert distinct_lst == [1, 2, 3, 4]\r\n\r\nlst = OrmCollection([\"apple\", \"banana\", \"orange\", \"f\", \"pear\", \"orange\"])\r\ndistinct_lst = lst.distinct()\r\nassert distinct_lst == [\"apple\", \"banana\", \"orange\", \"f\", \"pear\"]\r\n\r\norm_collection = OrmCollection(\r\n [\r\n {\"name\": \"Alice\", \"age\": 25, \"gender\": \"female\", \"taf\": \"psy\"},\r\n {\"name\": \"Alice\", \"age\": 80, \"gender\": \"male\", \"taf\": \"retraite\"},\r\n {\"name\": \"Bob\", \"age\": 40, \"gender\": \"male\", \"taf\": \"cia\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"taf\": \"etud\"},\r\n {\"name\": \"Charlie\", \"age\": 30, \"gender\": \"male\", \"taf\": \"prof\"},\r\n {\"name\": \"Dave\", \"age\": 30, \"gender\": \"male\", \"taf\": \"ing\"},\r\n {\"name\": \"Dave\", \"age\": 31, \"gender\": \"male\", \"taf\": \"chomor\"},\r\n ]\r\n)\r\ndistinct_coll = orm_collection.distinct(\"name\", \"age\")\r\nassert len(distinct_coll) == 6\r\nassert {(person[\"name\"], person[\"age\"]) for person in distinct_coll} == {\r\n (\"Alice\", 25),\r\n (\"Alice\", 80),\r\n (\"Dave\", 30),\r\n (\"Dave\", 31),\r\n (\"Bob\", 40),\r\n (\"Charlie\", 30),\r\n}\r\n\r\n```\r\n",
"bugtrack_url": null,
"license": "",
"summary": "Imporve object",
"version": "2.0.1",
"project_urls": {
"Bug Tracker": "https://github.com/mzakariabigdata/imobject/issues",
"Homepage": "https://github.com/mzakariabigdata/imobject"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "1b2655a8f80e80657e476ec0f41c637e41caab21be2bbf8df2cab0ba1708e727",
"md5": "f1d729ab8f7f010526b2f5e8bb118653",
"sha256": "425c30af65d82a037c784a6d99fe1583c3404b7efaf8278d75e9c627f6ece389"
},
"downloads": -1,
"filename": "imobject-2.0.1.tar.gz",
"has_sig": false,
"md5_digest": "f1d729ab8f7f010526b2f5e8bb118653",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 23572,
"upload_time": "2023-10-29T21:53:02",
"upload_time_iso_8601": "2023-10-29T21:53:02.725980Z",
"url": "https://files.pythonhosted.org/packages/1b/26/55a8f80e80657e476ec0f41c637e41caab21be2bbf8df2cab0ba1708e727/imobject-2.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-10-29 21:53:02",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "mzakariabigdata",
"github_project": "imobject",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "imobject"
}