autonomous-app 0.3.0__py3-none-any.whl → 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. autonomous/__init__.py +1 -1
  2. autonomous/ai/audioagent.py +1 -1
  3. autonomous/ai/imageagent.py +1 -1
  4. autonomous/ai/jsonagent.py +1 -1
  5. autonomous/ai/models/openai.py +81 -53
  6. autonomous/ai/oaiagent.py +1 -14
  7. autonomous/ai/textagent.py +1 -1
  8. autonomous/auth/autoauth.py +10 -10
  9. autonomous/auth/user.py +17 -2
  10. autonomous/db/__init__.py +42 -0
  11. autonomous/db/base/__init__.py +33 -0
  12. autonomous/db/base/common.py +62 -0
  13. autonomous/db/base/datastructures.py +476 -0
  14. autonomous/db/base/document.py +1230 -0
  15. autonomous/db/base/fields.py +767 -0
  16. autonomous/db/base/metaclasses.py +468 -0
  17. autonomous/db/base/utils.py +22 -0
  18. autonomous/db/common.py +79 -0
  19. autonomous/db/connection.py +472 -0
  20. autonomous/db/context_managers.py +313 -0
  21. autonomous/db/dereference.py +291 -0
  22. autonomous/db/document.py +1141 -0
  23. autonomous/db/errors.py +165 -0
  24. autonomous/db/fields.py +2732 -0
  25. autonomous/db/mongodb_support.py +24 -0
  26. autonomous/db/pymongo_support.py +80 -0
  27. autonomous/db/queryset/__init__.py +28 -0
  28. autonomous/db/queryset/base.py +2033 -0
  29. autonomous/db/queryset/field_list.py +88 -0
  30. autonomous/db/queryset/manager.py +58 -0
  31. autonomous/db/queryset/queryset.py +189 -0
  32. autonomous/db/queryset/transform.py +527 -0
  33. autonomous/db/queryset/visitor.py +189 -0
  34. autonomous/db/signals.py +59 -0
  35. autonomous/logger.py +3 -0
  36. autonomous/model/autoattr.py +56 -41
  37. autonomous/model/automodel.py +88 -34
  38. {autonomous_app-0.3.0.dist-info → autonomous_app-0.3.1.dist-info}/METADATA +2 -2
  39. autonomous_app-0.3.1.dist-info/RECORD +60 -0
  40. {autonomous_app-0.3.0.dist-info → autonomous_app-0.3.1.dist-info}/WHEEL +1 -1
  41. autonomous_app-0.3.0.dist-info/RECORD +0 -35
  42. {autonomous_app-0.3.0.dist-info → autonomous_app-0.3.1.dist-info}/LICENSE +0 -0
  43. {autonomous_app-0.3.0.dist-info → autonomous_app-0.3.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,189 @@
1
+ import copy
2
+ import warnings
3
+
4
+ from autonomous.db.errors import InvalidQueryError
5
+ from autonomous.db.queryset import transform
6
+
7
+ __all__ = ("Q", "QNode")
8
+
9
+
10
+ def warn_empty_is_deprecated():
11
+ msg = "'empty' property is deprecated in favour of using 'not bool(filter)'"
12
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
13
+
14
+
15
+ class QNodeVisitor:
16
+ """Base visitor class for visiting Q-object nodes in a query tree."""
17
+
18
+ def visit_combination(self, combination):
19
+ """Called by QCombination objects."""
20
+ return combination
21
+
22
+ def visit_query(self, query):
23
+ """Called by (New)Q objects."""
24
+ return query
25
+
26
+
27
+ class DuplicateQueryConditionsError(InvalidQueryError):
28
+ pass
29
+
30
+
31
+ class SimplificationVisitor(QNodeVisitor):
32
+ """Simplifies query trees by combining unnecessary 'and' connection nodes
33
+ into a single Q-object.
34
+ """
35
+
36
+ def visit_combination(self, combination):
37
+ if combination.operation == combination.AND:
38
+ # The simplification only applies to 'simple' queries
39
+ if all(isinstance(node, Q) for node in combination.children):
40
+ queries = [n.query for n in combination.children]
41
+ try:
42
+ return Q(**self._query_conjunction(queries))
43
+ except DuplicateQueryConditionsError:
44
+ # Cannot be simplified
45
+ pass
46
+ return combination
47
+
48
+ def _query_conjunction(self, queries):
49
+ """Merges query dicts - effectively &ing them together."""
50
+ query_ops = set()
51
+ combined_query = {}
52
+ for query in queries:
53
+ ops = set(query.keys())
54
+ # Make sure that the same operation isn't applied more than once
55
+ # to a single field
56
+ intersection = ops.intersection(query_ops)
57
+ if intersection:
58
+ raise DuplicateQueryConditionsError()
59
+
60
+ query_ops.update(ops)
61
+ combined_query.update(copy.deepcopy(query))
62
+ return combined_query
63
+
64
+
65
+ class QueryCompilerVisitor(QNodeVisitor):
66
+ """Compiles the nodes in a query tree to a PyMongo-compatible query
67
+ dictionary.
68
+ """
69
+
70
+ def __init__(self, document):
71
+ self.document = document
72
+
73
+ def visit_combination(self, combination):
74
+ operator = "$and"
75
+ if combination.operation == combination.OR:
76
+ operator = "$or"
77
+ return {operator: combination.children}
78
+
79
+ def visit_query(self, query):
80
+ return transform.query(self.document, **query.query)
81
+
82
+
83
+ class QNode:
84
+ """Base class for nodes in query trees."""
85
+
86
+ AND = 0
87
+ OR = 1
88
+
89
+ def to_query(self, document):
90
+ query = self.accept(SimplificationVisitor())
91
+ query = query.accept(QueryCompilerVisitor(document))
92
+ return query
93
+
94
+ def accept(self, visitor):
95
+ raise NotImplementedError
96
+
97
+ def _combine(self, other, operation):
98
+ """Combine this node with another node into a QCombination
99
+ object.
100
+ """
101
+ # If the other Q() is empty, ignore it and just use `self`.
102
+ if not bool(other):
103
+ return self
104
+
105
+ # Or if this Q is empty, ignore it and just use `other`.
106
+ if not bool(self):
107
+ return other
108
+
109
+ return QCombination(operation, [self, other])
110
+
111
+ @property
112
+ def empty(self):
113
+ warn_empty_is_deprecated()
114
+ return False
115
+
116
+ def __or__(self, other):
117
+ return self._combine(other, self.OR)
118
+
119
+ def __and__(self, other):
120
+ return self._combine(other, self.AND)
121
+
122
+
123
+ class QCombination(QNode):
124
+ """Represents the combination of several conditions by a given
125
+ logical operator.
126
+ """
127
+
128
+ def __init__(self, operation, children):
129
+ self.operation = operation
130
+ self.children = []
131
+ for node in children:
132
+ # If the child is a combination of the same type, we can merge its
133
+ # children directly into this combinations children
134
+ if isinstance(node, QCombination) and node.operation == operation:
135
+ self.children += node.children
136
+ else:
137
+ self.children.append(node)
138
+
139
+ def __repr__(self):
140
+ op = " & " if self.operation is self.AND else " | "
141
+ return "(%s)" % op.join([repr(node) for node in self.children])
142
+
143
+ def __bool__(self):
144
+ return bool(self.children)
145
+
146
+ def accept(self, visitor):
147
+ for i in range(len(self.children)):
148
+ if isinstance(self.children[i], QNode):
149
+ self.children[i] = self.children[i].accept(visitor)
150
+
151
+ return visitor.visit_combination(self)
152
+
153
+ @property
154
+ def empty(self):
155
+ warn_empty_is_deprecated()
156
+ return not bool(self.children)
157
+
158
+ def __eq__(self, other):
159
+ return (
160
+ self.__class__ == other.__class__
161
+ and self.operation == other.operation
162
+ and self.children == other.children
163
+ )
164
+
165
+
166
+ class Q(QNode):
167
+ """A simple query object, used in a query tree to build up more complex
168
+ query structures.
169
+ """
170
+
171
+ def __init__(self, **query):
172
+ self.query = query
173
+
174
+ def __repr__(self):
175
+ return "Q(**%s)" % repr(self.query)
176
+
177
+ def __bool__(self):
178
+ return bool(self.query)
179
+
180
+ def __eq__(self, other):
181
+ return self.__class__ == other.__class__ and self.query == other.query
182
+
183
+ def accept(self, visitor):
184
+ return visitor.visit_query(self)
185
+
186
+ @property
187
+ def empty(self):
188
+ warn_empty_is_deprecated()
189
+ return not bool(self.query)
@@ -0,0 +1,59 @@
1
+ __all__ = (
2
+ "pre_init",
3
+ "post_init",
4
+ "pre_save",
5
+ "pre_save_post_validation",
6
+ "post_save",
7
+ "pre_delete",
8
+ "post_delete",
9
+ )
10
+
11
+ signals_available = False
12
+ try:
13
+ from blinker import Namespace
14
+
15
+ signals_available = True
16
+ except ImportError:
17
+
18
+ class Namespace:
19
+ def signal(self, name, doc=None):
20
+ return _FakeSignal(name, doc)
21
+
22
+ class _FakeSignal:
23
+ """If blinker is unavailable, create a fake class with the same
24
+ interface that allows sending of signals but will fail with an
25
+ error on anything else. Instead of doing anything on send, it
26
+ will just ignore the arguments and do nothing instead.
27
+ """
28
+
29
+ def __init__(self, name, doc=None):
30
+ self.name = name
31
+ self.__doc__ = doc
32
+
33
+ def _fail(self, *args, **kwargs):
34
+ raise RuntimeError(
35
+ "signalling support is unavailable "
36
+ "because the blinker library is "
37
+ "not installed."
38
+ )
39
+
40
+ send = lambda *a, **kw: None # noqa
41
+ connect = disconnect = has_receivers_for = receivers_for = (
42
+ temporarily_connected_to
43
+ ) = _fail
44
+ del _fail
45
+
46
+
47
+ # the namespace for code signals. If you are not autonomous.db code, do
48
+ # not put signals in here. Create your own namespace instead.
49
+ _signals = Namespace()
50
+
51
+ pre_init = _signals.signal("pre_init")
52
+ post_init = _signals.signal("post_init")
53
+ pre_save = _signals.signal("pre_save")
54
+ pre_save_post_validation = _signals.signal("pre_save_post_validation")
55
+ post_save = _signals.signal("post_save")
56
+ pre_delete = _signals.signal("pre_delete")
57
+ post_delete = _signals.signal("post_delete")
58
+ pre_bulk_insert = _signals.signal("pre_bulk_insert")
59
+ post_bulk_insert = _signals.signal("post_bulk_insert")
autonomous/logger.py CHANGED
@@ -43,6 +43,7 @@ class Logger:
43
43
 
44
44
  def __call__(self, *args, **kwargs):
45
45
  if self.enabled:
46
+ is_printed = kwargs.pop("_print", False)
46
47
  caller = inspect.stack()[1]
47
48
  fn = caller.filename.split("/")[-1]
48
49
  msg = f"\n\n{'='*20}\t{fn}:{caller.function}()::{caller.lineno}\t{'='*20}\n"
@@ -57,6 +58,8 @@ class Logger:
57
58
  current.write(f"{msg}\n")
58
59
  with open(self.logarchive, "a") as archive:
59
60
  archive.write(f"{msg}\n")
61
+ if is_printed:
62
+ print(msg)
60
63
 
61
64
 
62
65
  log = Logger()
@@ -1,7 +1,5 @@
1
- from mongoengine.base import (
2
- get_document,
3
- )
4
- from mongoengine.fields import (
1
+ from autonomous import log
2
+ from autonomous.db.fields import (
5
3
  BooleanField,
6
4
  DateTimeField,
7
5
  DictField,
@@ -10,6 +8,7 @@ from mongoengine.fields import (
10
8
  EnumField,
11
9
  FileField,
12
10
  FloatField,
11
+ GenericLazyReferenceField,
13
12
  GenericReferenceField,
14
13
  ImageField,
15
14
  IntField,
@@ -17,8 +16,6 @@ from mongoengine.fields import (
17
16
  StringField,
18
17
  )
19
18
 
20
- from autonomous import log
21
-
22
19
 
23
20
  class StringAttr(StringField):
24
21
  pass
@@ -55,50 +52,68 @@ class ImageAttr(ImageField):
55
52
  class ReferenceAttr(GenericReferenceField):
56
53
  def __get__(self, instance, owner):
57
54
  try:
58
- # Attempt to retrieve the referenced document
59
- return super().__get__(instance, owner)
60
- except DoesNotExist:
61
- # If the document doesn't exist, return None
55
+ result = super().__get__(instance, owner)
56
+ except DoesNotExist as e:
57
+ log(f"ReferenceAttr Error: {e}")
62
58
  return None
59
+ return result
63
60
 
64
61
 
65
- class ListAttr(ListField):
66
- def clean_references(self, values):
67
- safe_values = []
68
- updated = False
62
+ # class ReferenceAttr(GenericLazyReferenceField):
63
+ # def __get__(self, instance, owner):
64
+ # try:
65
+ # result = super().__get__(instance, owner)
66
+ # except DoesNotExist as e:
67
+ # log(f"ReferenceAttr Error: {e}")
68
+ # return None
69
+ # return result.fetch() if result and result.pk else result
69
70
 
70
- for value in values:
71
- try:
72
- if isinstance(value, dict) and "_cls" in value:
73
- doc_cls = get_document(value["_cls"])
74
- value = doc_cls._get_db().dereference(value["_ref"])
75
- if value:
76
- safe_values.append(value)
77
- else:
78
- updated = True
79
- except DoesNotExist:
80
- updated = True
81
- log("hi")
82
- return safe_values, updated
71
+ # except DoesNotExist:
72
+ # If the document doesn't exist, return None
73
+ # return None
74
+
75
+ # def validate(self, value):
76
+ # if value is not None and not self.required:
77
+ # super().validate(value)
78
+
79
+
80
+ class ListAttr(ListField):
81
+ # pass
82
+ def __get__(self, instance, owner):
83
+ # log(instance, owner)
84
+ results = super().__get__(instance, owner) or []
85
+ # print(self.name, self.field, owner, results)
86
+ if isinstance(self.field, ReferenceAttr):
87
+ i = 0
88
+ while i < len(results):
89
+ try:
90
+ if not results[i]:
91
+ log(f"Removing Object: {results[i]}")
92
+ results.pop(i)
93
+ else:
94
+ i += 1
95
+ except DoesNotExist:
96
+ results.pop(i)
97
+ log(f"Object Not Found: {results[i]}")
98
+ # log(results)
99
+ return results
83
100
 
84
101
 
85
102
  class DictAttr(DictField):
86
- def clean_references(self, values):
87
- safe_values = {}
88
- updated = False
89
- for key, value in values.items():
103
+ def __get__(self, instance, owner):
104
+ # log(instance, owner)
105
+ results = super().__get__(instance, owner) or {}
106
+ log(self.name, self.field, owner, results)
107
+ for key, lazy_obj in results.items():
90
108
  try:
91
- if isinstance(value, dict) and "_cls" in value:
92
- doc_cls = get_document(value["_cls"])
93
- value = doc_cls._get_db().dereference(value["_ref"])
94
- if value:
95
- safe_values[key] = value
96
- else:
97
- updated = True
109
+ if hasattr(lazy_obj, "fetch"):
110
+ lazy_obj = (
111
+ lazy_obj.fetch() if lazy_obj and lazy_obj.pk else lazy_obj
112
+ )
98
113
  except DoesNotExist:
99
- updated = True
100
-
101
- return safe_values, updated
114
+ log(f"Object Not Found: {lazy_obj}")
115
+ results[key] = lazy_obj
116
+ return results
102
117
 
103
118
 
104
119
  class EnumAttr(EnumField):
@@ -4,48 +4,55 @@ import urllib.parse
4
4
  from datetime import datetime
5
5
 
6
6
  from bson import ObjectId
7
- from mongoengine import Document, connect
8
- from mongoengine.fields import DateTimeField
9
7
 
10
8
  from autonomous import log
11
-
12
- from .autoattr import DictAttr, ListAttr
9
+ from autonomous.db import Document, connect, signals
10
+ from autonomous.db.errors import ValidationError
11
+ from autonomous.db.fields import DateTimeField
12
+ from autonomous.model.autoattr import DictAttr, ListAttr
13
13
 
14
14
  host = os.getenv("DB_HOST", "db")
15
15
  port = os.getenv("DB_PORT", 27017)
16
16
  password = urllib.parse.quote_plus(str(os.getenv("DB_PASSWORD")))
17
17
  username = urllib.parse.quote_plus(str(os.getenv("DB_USERNAME")))
18
- db = os.getenv("DB_DB")
19
- connect(host=f"mongodb://{username}:{password}@{host}:{port}")
18
+ dbname = os.getenv("DB_DB")
19
+ # log(f"Connecting to MongoDB at {host}:{port} with {username}:{password} for {dbname}")
20
+ connect(host=f"mongodb://{username}:{password}@{host}:{port}/{dbname}?authSource=admin")
21
+ # log(f"{db}")
20
22
 
21
23
 
22
24
  class AutoModel(Document):
23
- meta = {"abstract": True, "allow_inheritance": True}
25
+ meta = {"abstract": True, "allow_inheritance": True, "strict": False}
24
26
  last_updated = DateTimeField(default=datetime.now)
25
27
 
26
- def __init__(self, *args, **kwargs):
27
- super().__init__(*args, **kwargs)
28
- if kwargs.pop("pk", None):
29
- self.reload()
30
- for k, v in kwargs.items():
31
- setattr(self, k, v)
32
- self.last_updated = datetime.now()
33
-
34
- for field_name, field in self._fields.items():
35
- value = getattr(self, field_name, None)
36
- # log(
37
- # f"Field: {field_name}, Type:{type(value)}, Value: {value}, {hasattr(field, "clean_references")}"
38
- # )
39
-
40
- if hasattr(field, "clean_references") and value:
41
- cleaned_values, updated = field.clean_references(value)
42
- # log(f"Cleaned Values: {cleaned_values}")
43
- if updated:
44
- setattr(self, field_name, cleaned_values)
45
-
46
28
  def __eq__(self, other):
47
29
  return self.pk == other.pk if other else False
48
30
 
31
+ @classmethod
32
+ def auto_pre_init(cls, sender, document, **kwargs):
33
+ values = kwargs.pop("values", None)
34
+ if pk := values.get("pk") or values.get("id"):
35
+ # Try to load the existing document from the database
36
+ if existing_doc := sender._get_collection().find_one({"_id": ObjectId(pk)}):
37
+ # Update the current instance with the existing data
38
+ existing_doc.pop("_id", None)
39
+ existing_doc.pop("_cls", None)
40
+ for k, v in existing_doc.items():
41
+ if not values.get(k):
42
+ values[k] = v
43
+
44
+ @classmethod
45
+ def _auto_pre_init(cls, sender, document, **kwargs):
46
+ sender.auto_pre_init(sender, document, **kwargs)
47
+
48
+ @classmethod
49
+ def auto_post_init(cls, sender, document, **kwargs):
50
+ document.last_updated = datetime.now()
51
+
52
+ @classmethod
53
+ def _auto_post_init(cls, sender, document, **kwargs):
54
+ sender.auto_post_init(sender, document, **kwargs)
55
+
49
56
  @classmethod
50
57
  def model_name(cls, qualified=False):
51
58
  """
@@ -58,7 +65,9 @@ class AutoModel(Document):
58
65
 
59
66
  @classmethod
60
67
  def load_model(cls, model):
61
- module_name, model = model.rsplit(".", 1) if "." in model else ("models", model)
68
+ module_name, model = (
69
+ model.rsplit(".", 1) if "." in model else (f"models.{model.lower()}", model)
70
+ )
62
71
  module = importlib.import_module(module_name)
63
72
  return getattr(module, model)
64
73
 
@@ -73,13 +82,22 @@ class AutoModel(Document):
73
82
  Returns:
74
83
  AutoModel or None: The retrieved AutoModel instance, or None if not found.
75
84
  """
76
- if pk and isinstance(pk, str):
85
+
86
+ if isinstance(pk, str):
77
87
  pk = ObjectId(pk)
88
+ elif isinstance(pk, dict) and "$oid" in pk:
89
+ pk = ObjectId(pk["$oid"])
78
90
  try:
79
- return cls.objects(pk=pk).get()
80
- except Exception as e:
81
- log(e)
91
+ return cls.objects.get(id=pk)
92
+ except cls.DoesNotExist as e:
93
+ log(f"Model {cls.__name__} with pk {pk} not found : {e}")
82
94
  return None
95
+ except ValidationError as e:
96
+ log(f"Model Validation failure {cls.__name__} [{pk}]: {e}")
97
+ return None
98
+ except Exception as e:
99
+ log(f"Error getting model {cls.__name__} with pk {pk}: {e}", _print=True)
100
+ raise e
83
101
 
84
102
  @classmethod
85
103
  def random(cls):
@@ -142,6 +160,20 @@ class AutoModel(Document):
142
160
  """
143
161
  return cls.objects(**kwargs).first()
144
162
 
163
+ @classmethod
164
+ def auto_pre_save(cls, sender, document, **kwargs):
165
+ """
166
+ Post-save hook for this model.
167
+ """
168
+ pass
169
+
170
+ @classmethod
171
+ def _auto_pre_save(cls, sender, document, **kwargs):
172
+ """
173
+ Post-save hook for this model.
174
+ """
175
+ sender.auto_pre_save(sender, document, **kwargs)
176
+
145
177
  def save(self):
146
178
  """
147
179
  Save this model to the database.
@@ -149,11 +181,33 @@ class AutoModel(Document):
149
181
  Returns:
150
182
  int: The primary key (pk) of the saved model.
151
183
  """
152
- # log(self.model_dump_json())
153
- return super().save()
184
+ # log(self.to_json())
185
+ obj = super().save()
186
+ self.pk = obj.pk
187
+ return self.pk
188
+
189
+ @classmethod
190
+ def auto_post_save(cls, sender, document, **kwargs):
191
+ """
192
+ Post-save hook for this model.
193
+ """
194
+ pass
195
+
196
+ @classmethod
197
+ def _auto_post_save(cls, sender, document, **kwargs):
198
+ """
199
+ Post-save hook for this model.
200
+ """
201
+ sender.auto_post_save(sender, document, **kwargs)
154
202
 
155
203
  def delete(self):
156
204
  """
157
205
  Delete this model from the database.
158
206
  """
159
207
  return super().delete()
208
+
209
+
210
+ signals.pre_init.connect(AutoModel._auto_pre_init)
211
+ signals.post_init.connect(AutoModel._auto_post_init)
212
+ signals.pre_save.connect(AutoModel._auto_pre_save)
213
+ signals.post_save.connect(AutoModel._auto_post_save)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: autonomous-app
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Containerized application framework built on Flask with additional libraries and tools for rapid development of web applications.
5
5
  Author-email: Steven A Moore <samoore@binghamton.edu>
6
6
  License: MIT License
@@ -34,9 +34,9 @@ License-File: LICENSE
34
34
  Requires-Dist: Flask
35
35
  Requires-Dist: setuptools
36
36
  Requires-Dist: python-dotenv
37
+ Requires-Dist: blinker
37
38
  Requires-Dist: PyGithub
38
39
  Requires-Dist: pygit2
39
- Requires-Dist: mongoengine
40
40
  Requires-Dist: pillow
41
41
  Requires-Dist: redis
42
42
  Requires-Dist: jsmin
@@ -0,0 +1,60 @@
1
+ autonomous/__init__.py,sha256=4zG57y3yMritw2TPxGgITZCNAcpJp2ZELW1iO8Wrlp0,95
2
+ autonomous/cli.py,sha256=z4AaGeWNW_uBLFAHng0J_lfS9v3fXemK1PeT85u4Eo4,42
3
+ autonomous/logger.py,sha256=NQtgEaTWNAWfLSgqSP7ksXj1GpOuCgoUV711kSMm-WA,2022
4
+ autonomous/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ autonomous/ai/audioagent.py,sha256=uZEhJ8_ctEvzshxJewaGdw-gh2Ts8lIcEysh0rlL62w,1040
6
+ autonomous/ai/imageagent.py,sha256=Y3n4OFD-UC9lSg1j-U9wRnyLLaRl0LjibHbriJwYF2c,981
7
+ autonomous/ai/jsonagent.py,sha256=P5HGuN7r7whgryZ2oCvSRY7jQlq0FdDK3-DtdnUG_N0,1321
8
+ autonomous/ai/oaiagent.py,sha256=Zrd4iijGfkFsF1Dbhhj0SeHoezec3kae8CrFrZQeqXQ,1346
9
+ autonomous/ai/textagent.py,sha256=pYzuoE7ENsxXjTSoVRMGvy7KQK0cS50SlWpY-1r7PiY,1220
10
+ autonomous/ai/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ autonomous/ai/models/openai.py,sha256=npavtBRWaxZuO3EtdFK1pm64wporJcTb_JDdxhMyhPI,11732
12
+ autonomous/apis/version_control/GHCallbacks.py,sha256=AyiUlYfV5JePi11GVyqYyXoj5UTbPKzS-HRRI94rjJo,1069
13
+ autonomous/apis/version_control/GHOrganization.py,sha256=mi2livdsGurKiifbvuLwiFbdDzL77IlEfhwEa-tG77I,1155
14
+ autonomous/apis/version_control/GHRepo.py,sha256=hTFHMkxSbSlVELfh8S6mq6ijkIKPRQO-Q5775ZjRKD4,4622
15
+ autonomous/apis/version_control/GHVersionControl.py,sha256=VIhVRxe6gJgozFWyhyKIu4spgSJI-GChiVJudnSyggI,196
16
+ autonomous/apis/version_control/__init__.py,sha256=tP0bAWYl1RwBRi62HsIidmgyqHuSlCUqwGuKUKKRugc,117
17
+ autonomous/auth/__init__.py,sha256=IW5tQ8VYwHIbDfMYA0wYgx4PprwcjUWV4EoIJ8HTlMU,161
18
+ autonomous/auth/autoauth.py,sha256=6GFs8xikCvPYXZ29bbc5baf603QvnE8tZQIIrAfTziY,3624
19
+ autonomous/auth/github.py,sha256=dHf84bJdV9rXGcvRLzWCPW9CvuA-VEmqYi_QQFwd2kY,886
20
+ autonomous/auth/google.py,sha256=cHmqbyNEPTKipc3WkYcD1XPOyqcWEFW0Ks4qJYmGvPw,1049
21
+ autonomous/auth/user.py,sha256=t8R7KsHp-QK3B_OS5ERSnQ4P8Tnhjehhmdqp5gcKxuU,2702
22
+ autonomous/db/__init__.py,sha256=9frkXJrl_OUemUQteXCTPqC8ECyxjE91Gi2mgTq26Fw,1159
23
+ autonomous/db/common.py,sha256=BUN2x_XuQBRFcq54TGPx4yLMLJdgytdbIt07QWr4CSM,2551
24
+ autonomous/db/connection.py,sha256=IhfJ8H5SZ44z7ptEez3T8QUPk88en9s3y9eKIpnIfg4,17747
25
+ autonomous/db/context_managers.py,sha256=_nH2ajCL8Xy90AuB2rKaryR4iF8Q8ksU3Nei_mZj-DE,9918
26
+ autonomous/db/dereference.py,sha256=Q_LkFwG5Be8XFKuwgvOIMb87R1DpavFbCOV2HdJV56Q,12573
27
+ autonomous/db/document.py,sha256=PGbCbkx3Los4zOj0Da6YcLCv_rR-xXp_7X6qivjAsL4,44429
28
+ autonomous/db/errors.py,sha256=_QeCotid1kmr7_W0QyH6NUrwwYN9eced_yyyiop0Xlw,4108
29
+ autonomous/db/fields.py,sha256=S79EaZCD5WZM-z7Fo3u4LsK-Rx3J5t4wDJorSanJ2qQ,93727
30
+ autonomous/db/mongodb_support.py,sha256=u0X-zpqTIZZP8o2-IDyKRKHL8ALLhvW1VSGtK3fLyos,626
31
+ autonomous/db/pymongo_support.py,sha256=UEZ4RHAGb_t1nuMUAJXMNs0vdH3dutxAH5mwFCmG6jI,2951
32
+ autonomous/db/signals.py,sha256=BM-M4hh4SrTbV9bZVIEWTG8mxgKn9Lo2rC7owLJz4yQ,1791
33
+ autonomous/db/base/__init__.py,sha256=qbVw-SlbJxlWu8UoPLQcwyRQ7Oso0r3aUit6Jqpoz40,1026
34
+ autonomous/db/base/common.py,sha256=YjvDGwmn-QoRplL9Xx2q3eUXEetgo3YureIGxbR36Y8,1540
35
+ autonomous/db/base/datastructures.py,sha256=fcgWe2JsfzTK3jbku3Teh0Iwvn5U5EhCpyeh9xr8bZ0,15850
36
+ autonomous/db/base/document.py,sha256=OM7CeJFZbxha6yKMiMCrHOlTELfOXusqJ8i6FjdFd0c,46652
37
+ autonomous/db/base/fields.py,sha256=c_FO9mryhdqzv4NdM1TnEl4WDoopy46I9UF1L8MVFFw,29146
38
+ autonomous/db/base/metaclasses.py,sha256=GVvJYcCxaW1ltEqyH4oNvT_srckEXDSHOtHVU_TAN70,18138
39
+ autonomous/db/base/utils.py,sha256=MH4FuEwh-5IcIinwNTkyTs-PqQLyyiMctcYMsNP85qk,617
40
+ autonomous/db/queryset/__init__.py,sha256=XT3__0BJCvQIQj3S_Mp7mPxNBkfdvXkdw56cg2gc86o,756
41
+ autonomous/db/queryset/base.py,sha256=aTq4C3K_YP8H6eE_HHn82C8I81l8uw1w0EPmCzcS7HM,76077
42
+ autonomous/db/queryset/field_list.py,sha256=qY50kgMYzloZXrOXnWT0PS_fBJCoThSioRvW9-HmhYA,2964
43
+ autonomous/db/queryset/manager.py,sha256=fXu95TlGChdJWTRA4OnY_Ik25JzezJ2_qPqmH78xJsY,2238
44
+ autonomous/db/queryset/queryset.py,sha256=Xvt1q7Olij9STbJkHm6dKrUIrgyJeY_uwJOYE9WUZvk,5942
45
+ autonomous/db/queryset/transform.py,sha256=UhBdDxYR_bWH0ECnaSw9g9YMwgWRZtsRl_q6PkqO9eY,19615
46
+ autonomous/db/queryset/visitor.py,sha256=AN09lR6hWYUlKJC7G1sktvnWy5hrFnpoQhi58bOXbA4,5470
47
+ autonomous/model/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
48
+ autonomous/model/autoattr.py,sha256=JvPpENa-bSaRSk0s1I1y5eqrKEYX8MzZUUybZD6Guhs,2820
49
+ autonomous/model/automodel.py,sha256=UYaXkl27y6nuS9tS22OXiHfQRg7OFmoYjP5HK47cU3Q,6496
50
+ autonomous/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
+ autonomous/storage/imagestorage.py,sha256=xxMu9gXZ3nGU9xsXNmHtk_9RtrALZ2QlX5XsR4SL7xc,4589
52
+ autonomous/storage/localstorage.py,sha256=FzrR6O9mMGAZt5dDgqzkeOQVfGRXCygR0kksz2MPpwE,2286
53
+ autonomous/tasks/__init__.py,sha256=pn7iZ14MhcHUdzcLkfkd4-45wgPP0tXahAz_cFgb_Tg,32
54
+ autonomous/tasks/autotask.py,sha256=aK5iapDhgcAic3F5ZYMAhNKJkOepj8yWwbMizKDzUwQ,4153
55
+ autonomous/utils/markdown.py,sha256=tf8vlHARiQO1X_aGbqlYozzP_TbdiDRT9EEP6aFRQo0,2153
56
+ autonomous_app-0.3.1.dist-info/LICENSE,sha256=-PHHSuDRkodHo3PEdMkDtoIdmLAOomMq6lsLaOetU8g,1076
57
+ autonomous_app-0.3.1.dist-info/METADATA,sha256=ri137pRjUmGCpW_jZvwWycCQOb6wS5hzs7pZGnopCH8,4188
58
+ autonomous_app-0.3.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
59
+ autonomous_app-0.3.1.dist-info/top_level.txt,sha256=ZyxWWDdbvZekF3UFunxl4BQsVDb_FOW3eTn0vun_jb4,11
60
+ autonomous_app-0.3.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (73.0.1)
2
+ Generator: setuptools (74.1.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5