hypern 0.3.3__cp310-cp310-win32.whl → 0.3.4__cp310-cp310-win32.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.
hypern/application.py CHANGED
@@ -436,8 +436,6 @@ class Hypern:
436
436
  server.set_auto_compression(enabled=self.auto_compression)
437
437
  server.set_mem_pool_capacity(min_capacity=self.args.min_capacity, max_capacity=self.args.max_capacity)
438
438
 
439
- server.optimize_routes()
440
-
441
439
  if self.database_config:
442
440
  server.set_database_config(config=self.database_config)
443
441
  if self.start_up_handler:
hypern/db/sql/field.py CHANGED
@@ -437,7 +437,7 @@ class ArrayField(Field):
437
437
  class ForeignKey(Field):
438
438
  """Foreign key field representing a relationship to another model."""
439
439
 
440
- def __init__(self, to_model: str, on_delete: str = "CASCADE", on_update: str = "CASCADE", **kwargs):
440
+ def __init__(self, to_model: str, related_field: str, on_delete: str = "CASCADE", on_update: str = "CASCADE", **kwargs):
441
441
  """
442
442
  Initialize a foreign key field.
443
443
 
@@ -455,6 +455,7 @@ class ForeignKey(Field):
455
455
  self.to_model = to_model
456
456
  self.on_delete = on_delete
457
457
  self.on_update = on_update
458
+ self.related_field = related_field
458
459
 
459
460
  def to_py_type(self, value: Any) -> Optional[int]:
460
461
  """
hypern/db/sql/model.py CHANGED
@@ -109,7 +109,7 @@ class Model(metaclass=MetaModel):
109
109
 
110
110
  @classmethod
111
111
  def _get_foreign_key_sql(cls, name, field) -> str:
112
- return f"FOREIGN KEY ({name}) REFERENCES {field.to_model}(id) ON DELETE {field.on_delete} ON UPDATE {field.on_update}"
112
+ return f"FOREIGN KEY ({name}) REFERENCES {field.to_model}({field.related_field}) ON DELETE {field.on_delete} ON UPDATE {field.on_update}"
113
113
 
114
114
  def save(self):
115
115
  query_object = QuerySet(self)
hypern/db/sql/query.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from enum import Enum
2
2
  from typing import Any, Dict, List, Tuple, Union
3
+ from hypern.db.sql.field import ForeignKey
3
4
 
4
5
 
5
6
  class JoinType(Enum):
@@ -98,7 +99,7 @@ class F:
98
99
  """Class for creating SQL expressions and column references"""
99
100
 
100
101
  def __init__(self, field: str):
101
- self.field = field.replace("__", ".") # Handle Django-style field references
102
+ self.field = field.replace("__", ".")
102
103
 
103
104
  def __add__(self, other):
104
105
  if isinstance(other, F):
@@ -356,6 +357,7 @@ class QuerySet:
356
357
  self._nowait = False
357
358
  self._skip_locked = False
358
359
  self._param_counter = 1
360
+ self._selected_related = set()
359
361
 
360
362
  def __get_next_param(self):
361
363
  param_name = f"${self._param_counter}"
@@ -372,11 +374,12 @@ class QuerySet:
372
374
  new_qs._nowait = self._nowait
373
375
  new_qs._skip_locked = self._skip_locked
374
376
  new_qs._param_counter = self._param_counter
377
+ new_qs._selected_related = self._selected_related.copy()
375
378
  return new_qs
376
379
 
377
380
  def select(self, *fields, distinct: bool = False) -> "QuerySet":
378
381
  qs = self.clone()
379
- qs.query_parts["select"] = list(fields)
382
+ qs.query_parts["select"] = list(map(lambda x: f"{qs.model.Meta.table_name}.{x}" if x != "*" else x, fields))
380
383
  qs._distinct = distinct
381
384
  return qs
382
385
 
@@ -426,10 +429,10 @@ class QuerySet:
426
429
  return self._process_standard_value(field, op, value)
427
430
 
428
431
  def _process_f_value(self, field: str, op: str, value: F) -> Tuple[str, List]:
429
- return f"{field} {op} {value.field}", []
432
+ return f"{self.model.Meta.table_name}.{field} {op} {value.field}", []
430
433
 
431
434
  def _process_expression_value(self, field: str, op: str, value: Expression) -> Tuple[str, List]:
432
- return f"{field} {op} {value.sql}", value.params
435
+ return f"{self.model.Meta.table_name}.{field} {op} {value.sql}", value.params
433
436
 
434
437
  def _process_standard_value(self, field: str, op: str, value: Any) -> Tuple[str, List]:
435
438
  op_map = {
@@ -453,25 +456,26 @@ class QuerySet:
453
456
  return self._process_op_map_value(field, op, value, op_map)
454
457
  else:
455
458
  param_name = self.__get_next_param()
456
- return f"{field} = {param_name}", [value]
459
+ return f"{self.model.Meta.table_name}.{field} = {param_name}", [value]
457
460
 
458
461
  def _process_op_map_value(self, field: str, op: str, value: Any, op_map: dict) -> Tuple[str, List]:
459
462
  param_name = self.__get_next_param()
463
+ combine_field_name = f"{self.model.Meta.table_name}.{field}"
460
464
  if op in ("contains", "icontains"):
461
- return f"{field} {op_map[op]} {param_name}", [f"%{value}%"]
465
+ return f"{combine_field_name} {op_map[op]} {param_name}", [f"%{value}%"]
462
466
  elif op == "startswith":
463
- return f"{field} {op_map[op]} {param_name}", [f"{value}%"]
467
+ return f"{combine_field_name} {op_map[op]} {param_name}", [f"{value}%"]
464
468
  elif op == "endswith":
465
- return f"{field} {op_map[op]} {param_name}", [f"%{value}"]
469
+ return f"{combine_field_name} {op_map[op]} {param_name}", [f"%{value}"]
466
470
  elif op == "isnull":
467
- return f"{field} {Operator.IS_NULL.value if value else Operator.IS_NOT_NULL.value}", []
471
+ return f"{combine_field_name} {Operator.IS_NULL.value if value else Operator.IS_NOT_NULL.value}", []
468
472
  elif op == "between":
469
- return f"{field} {op_map[op]} {param_name} AND {param_name}", [value[0], value[1]]
473
+ return f"{combine_field_name} {op_map[op]} {param_name} AND {param_name}", [value[0], value[1]]
470
474
  elif op in ("in", "not_in"):
471
475
  placeholders = ",".join(["{param_name}" for _ in value])
472
- return f"{field} {op_map[op]} ({placeholders})", list(value)
476
+ return f"{combine_field_name} {op_map[op]} ({placeholders})", list(value)
473
477
  else:
474
- return f"{field} {op_map[op]} {param_name}", [value]
478
+ return f"{combine_field_name} {op_map[op]} {param_name}", [value]
475
479
 
476
480
  def where(self, *args, **kwargs) -> "QuerySet":
477
481
  qs = self.clone()
@@ -535,22 +539,36 @@ class QuerySet:
535
539
  elif field.startswith("-"):
536
540
  order_parts.append(f"{field[1:]} DESC")
537
541
  else:
538
- order_parts.append(f"{field} ASC")
542
+ order_parts.append(f"{qs.model.Meta.table_name}.{field} ASC")
539
543
 
540
544
  qs.query_parts["order_by"] = order_parts
541
545
  return qs
542
546
 
543
- def join(self, table: str, on: Union[str, Expression], join_type: Union[str, JoinType] = JoinType.INNER) -> "QuerySet":
547
+ def select_related(self, *fields) -> "QuerySet":
548
+ """
549
+ Include related objects in the query results.
550
+
551
+ Args:
552
+ *fields: Names of foreign key fields to include
553
+ """
554
+ qs = self.clone()
555
+ for field in fields:
556
+ if field in qs.model._fields and isinstance(qs.model._fields[field], ForeignKey):
557
+ qs._selected_related.add(field)
558
+ return qs
559
+
560
+ def join(self, table: Any, on: Union[str, Expression], join_type: Union[str, JoinType] = JoinType.INNER) -> "QuerySet":
544
561
  qs = self.clone()
562
+ joined_table = table.Meta.table_name if hasattr(table, "Meta") else table
545
563
 
546
564
  if isinstance(join_type, JoinType):
547
565
  join_type = join_type.value
548
566
 
549
567
  if isinstance(on, Expression):
550
- qs.query_parts["joins"].append(f"{join_type} {table} ON {on.sql}")
568
+ qs.query_parts["joins"].append(f"{join_type} {joined_table} ON {on.sql}")
551
569
  qs.params.extend(on.params)
552
570
  else:
553
- qs.query_parts["joins"].append(f"{join_type} {table} ON {on}")
571
+ qs.query_parts["joins"].append(f"{join_type} {joined_table} ON {on}")
554
572
 
555
573
  return qs
556
574
 
@@ -565,7 +583,7 @@ class QuerySet:
565
583
  group_parts.append(field.sql)
566
584
  qs.params.extend(field.params)
567
585
  else:
568
- group_parts.append(str(field))
586
+ group_parts.append(f"{qs.model.Meta.table_name}.{field}")
569
587
 
570
588
  qs.query_parts["group_by"] = group_parts
571
589
  return qs
@@ -607,7 +625,7 @@ class QuerySet:
607
625
  partition_parts.append(field.sql)
608
626
  qs.params.extend(field.params)
609
627
  else:
610
- partition_parts.append(str(field))
628
+ partition_parts.append(f"{self.model.Meta.table_name}.{field}")
611
629
  return f"PARTITION BY {', '.join(partition_parts)}"
612
630
 
613
631
  def _process_order_by(self, order_by: List, qs: "QuerySet") -> str:
@@ -619,9 +637,9 @@ class QuerySet:
619
637
  order_parts.append(field.sql)
620
638
  qs.params.extend(field.params)
621
639
  elif field.startswith("-"):
622
- order_parts.append(f"{field[1:]} DESC")
640
+ order_parts.append(f"{qs.model.Meta.table_name}.{field[1:]} DESC")
623
641
  else:
624
- order_parts.append(f"{field} ASC")
642
+ order_parts.append(f"{qs.model.Meta.table_name}.{field} ASC")
625
643
  return f"ORDER BY {', '.join(order_parts)}"
626
644
 
627
645
  def limit(self, limit: int) -> "QuerySet":
@@ -726,7 +744,14 @@ class QuerySet:
726
744
  select_clause = "SELECT"
727
745
  if self._distinct:
728
746
  select_clause += " DISTINCT"
729
- select_clause += " " + ", ".join(self.query_parts["select"])
747
+
748
+ # Add selected fields
749
+ select_related_fields = []
750
+ for field in self._selected_related:
751
+ related_table = self.model._fields[field].to_model
752
+ select_related_fields.append(f"{related_table}.*")
753
+
754
+ select_clause += " " + ", ".join(self.query_parts["select"] + select_related_fields)
730
755
  parts.append(select_clause)
731
756
 
732
757
  def _add_from_clause(self, parts):
Binary file
hypern/hypern.pyi CHANGED
@@ -191,7 +191,6 @@ class Server:
191
191
  def set_auto_compression(self, enabled: bool) -> None: ...
192
192
  def set_database_config(self, config: DatabaseConfig) -> None: ...
193
193
  def set_mem_pool_capacity(self, min_capacity: int, max_capacity: int) -> None: ...
194
- def optimize_routes(self) -> None: ...
195
194
 
196
195
  class Route:
197
196
  path: str
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hypern
3
- Version: 0.3.3
3
+ Version: 0.3.4
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -1,7 +1,7 @@
1
- hypern-0.3.3.dist-info/METADATA,sha256=VDUnlR9iin2qEAagUwnOdvZL1vC4dMeNM1oBrwl-rZ8,3819
2
- hypern-0.3.3.dist-info/WHEEL,sha256=HVA0wOUnIw3WSu8DET4aOHFt1dH_siSsnV6db_YgIxE,92
3
- hypern-0.3.3.dist-info/licenses/LICENSE,sha256=qbYKAIJLS6jYg5hYncKE7OtWmqOtpVTvKNkwOa0Iwwg,1328
4
- hypern/application.py,sha256=TZKwSHpWSOaValZtogmMO18l8U_xOpFN7cARMFK1hns,18432
1
+ hypern-0.3.4.dist-info/METADATA,sha256=wJ9_iA8bw0-Sc-a3AtzB0aCWhN4iPavHZjQfZgEpats,3819
2
+ hypern-0.3.4.dist-info/WHEEL,sha256=HVA0wOUnIw3WSu8DET4aOHFt1dH_siSsnV6db_YgIxE,92
3
+ hypern-0.3.4.dist-info/licenses/LICENSE,sha256=qbYKAIJLS6jYg5hYncKE7OtWmqOtpVTvKNkwOa0Iwwg,1328
4
+ hypern/application.py,sha256=DCYFtU8e8NhQtmfaXbUfOxR2_Y3fEn-pzce9OOs6S4U,18396
5
5
  hypern/args_parser.py,sha256=zTfLfBoKBvYWxdPjabTfZsCtYF3La3PT0TD8dfLMeM4,2815
6
6
  hypern/auth/authorization.py,sha256=-NprZsI0np889ZN1fp-MiVFrPoMNzUtatBJaCMtkllM,32
7
7
  hypern/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -32,9 +32,9 @@ hypern/db/nosql/addons/password.py,sha256=jfZxvWFm6nV9EWpXq5Mj-jpqnl9QbokZj9WT14
32
32
  hypern/db/nosql/addons/unicode.py,sha256=LaDpLfdoTcJuASPE-8fqOVD05H_uOx8gOdnyDn5Iu0c,268
33
33
  hypern/db/nosql/addons/__init__.py,sha256=WEtPM8sPHilvga7zxwqvINeTkF0hdcfgPcAnHc4MASE,125
34
34
  hypern/db/nosql/__init__.py,sha256=MH9YvlbRlbBCrQVNOdfTaK-hINwJxbJLmxwY9Mei7I8,644
35
- hypern/db/sql/field.py,sha256=_5Et9pPmTI_bhUFN7PgdSiozip-Iv0eH2491J_WUvXU,20009
36
- hypern/db/sql/model.py,sha256=5GtH3v6LfYIENlBN1NpIjZpsYFQyo36jX-b6jO1lNdU,3894
37
- hypern/db/sql/query.py,sha256=_kBZbdQckYyawSIcuaUrE4C6eWgpeWyK1JVR3JWdh60,31964
35
+ hypern/db/sql/field.py,sha256=tSs8iaYjy-K6nplJJ-1X4OQddzW76cfBlx9xTrG_NbQ,20073
36
+ hypern/db/sql/model.py,sha256=BLRmOlmfn6ibedR9Bv_rHErSruudJ24B9-nDbRHqWm4,3913
37
+ hypern/db/sql/query.py,sha256=MXiphm4pXBz6Axbdoc5rg11XEmw_UahTCdppowyXJxY,33329
38
38
  hypern/db/sql/__init__.py,sha256=lCOGNTHaXNSJbuLLIOe2IWWNmX0MFQFPNCl2yytD2Xs,261
39
39
  hypern/db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
40
  hypern/enum.py,sha256=KcVziJj7vWvyie0r2rtxhrLzdtkZAsf0DY58oJ4tQl4,360
@@ -44,7 +44,7 @@ hypern/gateway/gateway.py,sha256=26K2qvJUR-0JnN4IlhwvSSt7EYcpYrBVDuzZ1ivQQ34,147
44
44
  hypern/gateway/proxy.py,sha256=w1wcTplDnVrfjn7hb0M0yBVth5TGl88irF-MUYHysQQ,2463
45
45
  hypern/gateway/service.py,sha256=PkRaM08olqM_j_4wRjEJCR8X8ZysAF2WOcfhWjaX2eo,1701
46
46
  hypern/gateway/__init__.py,sha256=TpFWtqnJerW1-jCWq5fjypJcw9Y6ytyrkvkzby1Eg0E,235
47
- hypern/hypern.pyi,sha256=4qHekIzH-I6CYch8PwYMus9Ou-JI901kgaLOGsnlOog,9389
47
+ hypern/hypern.pyi,sha256=yXaWGPt598gwPN-CT1ARDdwOSqryZCBFuDLQC8gRd1U,9345
48
48
  hypern/i18n/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  hypern/logging/logger.py,sha256=WACam_IJiCMXX0hGVKMGSxUQpY4DgAXy7M1dD3q-Z9s,3256
50
50
  hypern/logging/__init__.py,sha256=6eVriyncsJ4J73fGYhoejv9MX7aGTkRezTpPxO4DX1I,52
@@ -80,5 +80,5 @@ hypern/ws/route.py,sha256=fGQ2RC708MPOiiIHPUo8aZ-oK379TTAyQYm4htNA5jM,803
80
80
  hypern/ws/__init__.py,sha256=dhRoRY683_rfPfSPM5qUczfTuyYDeuLOCFxY4hIdKt8,131
81
81
  hypern/ws.py,sha256=F6SA2Z1KVnqTEX8ssvOXqCtudUS4eo30JsiIsvfbHnE,394
82
82
  hypern/__init__.py,sha256=9Ww_aUQ0vJls0tOq7Yw1_TVOCRsa5bHJ-RtnSeComwk,119
83
- hypern/hypern.cp310-win32.pyd,sha256=UG5K9FFyd-gT5lFBkOff3MhU_DTJnyLbInAA2PI8qKs,9836032
84
- hypern-0.3.3.dist-info/RECORD,,
83
+ hypern/hypern.cp310-win32.pyd,sha256=eUc0V3DWmjWn8gTIYvxXkVt2xQiHMTAhBeX9h0B2d00,9796608
84
+ hypern-0.3.4.dist-info/RECORD,,
File without changes