dreadnode 1.0.3__tar.gz → 1.0.4__tar.gz
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.
- {dreadnode-1.0.3 → dreadnode-1.0.4}/PKG-INFO +1 -1
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/__init__.py +13 -3
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/main.py +39 -9
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/metric.py +3 -2
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/tracing/span.py +39 -35
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/util.py +8 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/pyproject.toml +2 -2
- {dreadnode-1.0.3 → dreadnode-1.0.4}/README.md +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/api/__init__.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/api/client.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/api/models.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/api/util.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/artifact/__init__.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/artifact/merger.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/artifact/storage.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/artifact/tree_builder.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/constants.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/integrations/__init__.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/integrations/transformers.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/object.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/py.typed +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/serialization.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/task.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/tracing/__init__.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/tracing/constants.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/tracing/exporters.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/types.py +0 -0
- {dreadnode-1.0.3 → dreadnode-1.0.4}/dreadnode/version.py +0 -0
|
@@ -16,6 +16,7 @@ run = DEFAULT_INSTANCE.run
|
|
|
16
16
|
scorer = DEFAULT_INSTANCE.scorer
|
|
17
17
|
task_span = DEFAULT_INSTANCE.task_span
|
|
18
18
|
push_update = DEFAULT_INSTANCE.push_update
|
|
19
|
+
tag = DEFAULT_INSTANCE.tag
|
|
19
20
|
|
|
20
21
|
log_metric = DEFAULT_INSTANCE.log_metric
|
|
21
22
|
log_param = DEFAULT_INSTANCE.log_param
|
|
@@ -33,19 +34,28 @@ __all__ = [
|
|
|
33
34
|
"Metric",
|
|
34
35
|
"MetricDict",
|
|
35
36
|
"Object",
|
|
36
|
-
"Run",
|
|
37
37
|
"RunSpan",
|
|
38
|
-
"Score",
|
|
39
38
|
"Scorer",
|
|
40
39
|
"Span",
|
|
41
40
|
"Task",
|
|
42
41
|
"TaskSpan",
|
|
43
|
-
"
|
|
42
|
+
"api",
|
|
44
43
|
"configure",
|
|
44
|
+
"link_objects",
|
|
45
|
+
"log_artifact",
|
|
46
|
+
"log_input",
|
|
47
|
+
"log_inputs",
|
|
45
48
|
"log_metric",
|
|
49
|
+
"log_output",
|
|
46
50
|
"log_param",
|
|
51
|
+
"log_params",
|
|
52
|
+
"push_update",
|
|
47
53
|
"run",
|
|
54
|
+
"scorer",
|
|
48
55
|
"shutdown",
|
|
49
56
|
"span",
|
|
57
|
+
"tag",
|
|
50
58
|
"task",
|
|
59
|
+
"task_span",
|
|
60
|
+
"task_span",
|
|
51
61
|
]
|
|
@@ -2,7 +2,6 @@ import contextlib
|
|
|
2
2
|
import inspect
|
|
3
3
|
import os
|
|
4
4
|
import random
|
|
5
|
-
import re
|
|
6
5
|
import typing as t
|
|
7
6
|
from dataclasses import dataclass
|
|
8
7
|
from datetime import datetime, timezone
|
|
@@ -53,7 +52,7 @@ from dreadnode.types import (
|
|
|
53
52
|
JsonDict,
|
|
54
53
|
JsonValue,
|
|
55
54
|
)
|
|
56
|
-
from dreadnode.util import handle_internal_errors
|
|
55
|
+
from dreadnode.util import clean_str, handle_internal_errors
|
|
57
56
|
from dreadnode.version import VERSION
|
|
58
57
|
|
|
59
58
|
if t.TYPE_CHECKING:
|
|
@@ -503,7 +502,7 @@ class Dreadnode:
|
|
|
503
502
|
_label = label or func_name
|
|
504
503
|
|
|
505
504
|
# conform our label for sanity
|
|
506
|
-
_label =
|
|
505
|
+
_label = clean_str(_label)
|
|
507
506
|
|
|
508
507
|
_attributes = attributes or {}
|
|
509
508
|
_attributes["code.function"] = func_name
|
|
@@ -570,7 +569,7 @@ class Dreadnode:
|
|
|
570
569
|
if (run := current_run_span.get()) is None:
|
|
571
570
|
raise RuntimeError("Task spans must be created within a run")
|
|
572
571
|
|
|
573
|
-
label = label or
|
|
572
|
+
label = label or clean_str(name)
|
|
574
573
|
return TaskSpan(
|
|
575
574
|
name=name,
|
|
576
575
|
label=label,
|
|
@@ -681,6 +680,31 @@ class Dreadnode:
|
|
|
681
680
|
autolog=autolog,
|
|
682
681
|
)
|
|
683
682
|
|
|
683
|
+
def tag(self, *tag: str, to: ToObject = "task-or-run") -> None:
|
|
684
|
+
"""
|
|
685
|
+
Add one or many tags to the current task or run.
|
|
686
|
+
|
|
687
|
+
Example:
|
|
688
|
+
```
|
|
689
|
+
with dreadnode.run("my_run") as run:
|
|
690
|
+
run.tag("my_tag")
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
Args:
|
|
694
|
+
tag: The tag to attach to the task or run.
|
|
695
|
+
to: The target object to log the tag to. Can be "task-or-run" or "run".
|
|
696
|
+
Defaults to "task-or-run". If "task-or-run", the tag will be logged
|
|
697
|
+
to the current task or run, whichever is the nearest ancestor.
|
|
698
|
+
"""
|
|
699
|
+
task = current_task_span.get()
|
|
700
|
+
run = current_run_span.get()
|
|
701
|
+
|
|
702
|
+
target = (task or run) if to == "task-or-run" else run
|
|
703
|
+
if target is None:
|
|
704
|
+
raise RuntimeError("Tagging must be done within a run")
|
|
705
|
+
|
|
706
|
+
target.add_tags(tag)
|
|
707
|
+
|
|
684
708
|
@handle_internal_errors()
|
|
685
709
|
def push_update(self) -> None:
|
|
686
710
|
"""
|
|
@@ -777,7 +801,7 @@ class Dreadnode:
|
|
|
777
801
|
mode: MetricAggMode | None = None,
|
|
778
802
|
attributes: JsonDict | None = None,
|
|
779
803
|
to: ToObject = "task-or-run",
|
|
780
|
-
) ->
|
|
804
|
+
) -> Metric:
|
|
781
805
|
"""
|
|
782
806
|
Log a single metric to the current task or run.
|
|
783
807
|
|
|
@@ -809,6 +833,9 @@ class Dreadnode:
|
|
|
809
833
|
to: The target object to log the metric to. Can be "task-or-run" or "run".
|
|
810
834
|
Defaults to "task-or-run". If "task-or-run", the metric will be logged
|
|
811
835
|
to the current task or run, whichever is the nearest ancestor.
|
|
836
|
+
|
|
837
|
+
Returns:
|
|
838
|
+
The logged metric object.
|
|
812
839
|
"""
|
|
813
840
|
|
|
814
841
|
@t.overload
|
|
@@ -820,7 +847,7 @@ class Dreadnode:
|
|
|
820
847
|
origin: t.Any | None = None,
|
|
821
848
|
mode: MetricAggMode | None = None,
|
|
822
849
|
to: ToObject = "task-or-run",
|
|
823
|
-
) ->
|
|
850
|
+
) -> Metric:
|
|
824
851
|
"""
|
|
825
852
|
Log a single metric to the current task or run.
|
|
826
853
|
|
|
@@ -848,6 +875,9 @@ class Dreadnode:
|
|
|
848
875
|
to: The target object to log the metric to. Can be "task-or-run" or "run".
|
|
849
876
|
Defaults to "task-or-run". If "task-or-run", the metric will be logged
|
|
850
877
|
to the current task or run, whichever is the nearest ancestor.
|
|
878
|
+
|
|
879
|
+
Returns:
|
|
880
|
+
The logged metric object.
|
|
851
881
|
"""
|
|
852
882
|
|
|
853
883
|
@handle_internal_errors()
|
|
@@ -862,7 +892,7 @@ class Dreadnode:
|
|
|
862
892
|
mode: MetricAggMode | None = None,
|
|
863
893
|
attributes: JsonDict | None = None,
|
|
864
894
|
to: ToObject = "task-or-run",
|
|
865
|
-
) ->
|
|
895
|
+
) -> Metric:
|
|
866
896
|
task = current_task_span.get()
|
|
867
897
|
run = current_run_span.get()
|
|
868
898
|
|
|
@@ -877,7 +907,7 @@ class Dreadnode:
|
|
|
877
907
|
float(value), step, timestamp or datetime.now(timezone.utc), attributes or {}
|
|
878
908
|
)
|
|
879
909
|
)
|
|
880
|
-
target.log_metric(key, metric, origin=origin, mode=mode)
|
|
910
|
+
return target.log_metric(key, metric, origin=origin, mode=mode)
|
|
881
911
|
|
|
882
912
|
@handle_internal_errors()
|
|
883
913
|
def log_artifact(
|
|
@@ -926,7 +956,7 @@ class Dreadnode:
|
|
|
926
956
|
def log_input(
|
|
927
957
|
self,
|
|
928
958
|
name: str,
|
|
929
|
-
value:
|
|
959
|
+
value: t.Any,
|
|
930
960
|
*,
|
|
931
961
|
label: str | None = None,
|
|
932
962
|
to: ToObject = "task-or-run",
|
|
@@ -68,7 +68,7 @@ class Metric:
|
|
|
68
68
|
This will modify the metric in place.
|
|
69
69
|
|
|
70
70
|
Args:
|
|
71
|
-
mode: The mode to apply. One of "sum", "min", "max", or "
|
|
71
|
+
mode: The mode to apply. One of "sum", "min", "max", or "count".
|
|
72
72
|
others: A list of other metrics to apply the mode to.
|
|
73
73
|
|
|
74
74
|
Returns:
|
|
@@ -87,7 +87,8 @@ class Metric:
|
|
|
87
87
|
prior_values = [m.value for m in sorted(others, key=lambda m: m.timestamp)]
|
|
88
88
|
|
|
89
89
|
if mode == "sum":
|
|
90
|
-
|
|
90
|
+
# Take the max of the priors because they might already be summed
|
|
91
|
+
self.value += max(prior_values) if prior_values else 0
|
|
91
92
|
elif mode == "min":
|
|
92
93
|
self.value = min([self.value, *prior_values])
|
|
93
94
|
elif mode == "max":
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
import re
|
|
3
2
|
import types
|
|
4
3
|
import typing as t
|
|
5
4
|
from contextvars import ContextVar, Token
|
|
@@ -32,6 +31,7 @@ from dreadnode.metric import Metric, MetricAggMode, MetricDict
|
|
|
32
31
|
from dreadnode.object import Object, ObjectRef, ObjectUri, ObjectVal
|
|
33
32
|
from dreadnode.serialization import Serialized, serialize
|
|
34
33
|
from dreadnode.types import UNSET, AnyDict, JsonDict, JsonValue, Unset
|
|
34
|
+
from dreadnode.util import clean_str
|
|
35
35
|
from dreadnode.version import VERSION
|
|
36
36
|
|
|
37
37
|
from .constants import (
|
|
@@ -92,11 +92,16 @@ class Span(ReadableSpan):
|
|
|
92
92
|
) -> None:
|
|
93
93
|
self._label = label or ""
|
|
94
94
|
self._span_name = name
|
|
95
|
+
|
|
96
|
+
tags = [tags] if isinstance(tags, str) else list(tags or [])
|
|
97
|
+
tags = [clean_str(t) for t in tags]
|
|
98
|
+
self.tags: tuple[str, ...] = uniquify_sequence(tags)
|
|
99
|
+
|
|
95
100
|
self._pre_attributes = {
|
|
96
101
|
SPAN_ATTRIBUTE_VERSION: VERSION,
|
|
97
102
|
SPAN_ATTRIBUTE_TYPE: type,
|
|
98
103
|
SPAN_ATTRIBUTE_LABEL: self._label,
|
|
99
|
-
SPAN_ATTRIBUTE_TAGS_:
|
|
104
|
+
SPAN_ATTRIBUTE_TAGS_: self.tags,
|
|
100
105
|
**attributes,
|
|
101
106
|
}
|
|
102
107
|
self._tracer = tracer
|
|
@@ -145,6 +150,8 @@ class Span(ReadableSpan):
|
|
|
145
150
|
SPAN_ATTRIBUTE_SCHEMA,
|
|
146
151
|
attributes_json_schema(self._schema) if self._schema else r"{}",
|
|
147
152
|
)
|
|
153
|
+
self._span.set_attribute(SPAN_ATTRIBUTE_TAGS_, self.tags)
|
|
154
|
+
|
|
148
155
|
self._span.__exit__(exc_type, exc_value, traceback)
|
|
149
156
|
|
|
150
157
|
OPEN_SPANS.discard(self._span) # type: ignore [arg-type]
|
|
@@ -167,13 +174,14 @@ class Span(ReadableSpan):
|
|
|
167
174
|
return False
|
|
168
175
|
return self._span.is_recording()
|
|
169
176
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
177
|
+
def set_tags(self, tags: t.Sequence[str]) -> None:
|
|
178
|
+
tags = [tags] if isinstance(tags, str) else list(tags)
|
|
179
|
+
tags = [clean_str(t) for t in tags]
|
|
180
|
+
self.tags = uniquify_sequence(tags)
|
|
173
181
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
self.
|
|
182
|
+
def add_tags(self, tags: t.Sequence[str]) -> None:
|
|
183
|
+
tags = [tags] if isinstance(tags, str) else list(tags)
|
|
184
|
+
self.set_tags([*self.tags, *tags])
|
|
177
185
|
|
|
178
186
|
def set_attribute(
|
|
179
187
|
self,
|
|
@@ -485,7 +493,7 @@ class RunSpan(Span):
|
|
|
485
493
|
label: str | None = None,
|
|
486
494
|
**attributes: JsonValue,
|
|
487
495
|
) -> None:
|
|
488
|
-
label = label or
|
|
496
|
+
label = label or clean_str(name)
|
|
489
497
|
hash_ = self.log_object(
|
|
490
498
|
value,
|
|
491
499
|
label=label,
|
|
@@ -533,7 +541,7 @@ class RunSpan(Span):
|
|
|
533
541
|
mode: MetricAggMode | None = None,
|
|
534
542
|
prefix: str | None = None,
|
|
535
543
|
attributes: JsonDict | None = None,
|
|
536
|
-
) ->
|
|
544
|
+
) -> Metric: ...
|
|
537
545
|
|
|
538
546
|
@t.overload
|
|
539
547
|
def log_metric(
|
|
@@ -544,7 +552,7 @@ class RunSpan(Span):
|
|
|
544
552
|
origin: t.Any | None = None,
|
|
545
553
|
mode: MetricAggMode | None = None,
|
|
546
554
|
prefix: str | None = None,
|
|
547
|
-
) ->
|
|
555
|
+
) -> Metric: ...
|
|
548
556
|
|
|
549
557
|
def log_metric(
|
|
550
558
|
self,
|
|
@@ -557,7 +565,7 @@ class RunSpan(Span):
|
|
|
557
565
|
mode: MetricAggMode | None = None,
|
|
558
566
|
prefix: str | None = None,
|
|
559
567
|
attributes: JsonDict | None = None,
|
|
560
|
-
) ->
|
|
568
|
+
) -> Metric:
|
|
561
569
|
metric = (
|
|
562
570
|
value
|
|
563
571
|
if isinstance(value, Metric)
|
|
@@ -566,7 +574,7 @@ class RunSpan(Span):
|
|
|
566
574
|
)
|
|
567
575
|
)
|
|
568
576
|
|
|
569
|
-
key =
|
|
577
|
+
key = clean_str(key)
|
|
570
578
|
if prefix is not None:
|
|
571
579
|
key = f"{prefix}.{key}"
|
|
572
580
|
|
|
@@ -583,6 +591,8 @@ class RunSpan(Span):
|
|
|
583
591
|
metric = metric.apply_mode(mode, metrics)
|
|
584
592
|
metrics.append(metric)
|
|
585
593
|
|
|
594
|
+
return metric
|
|
595
|
+
|
|
586
596
|
@property
|
|
587
597
|
def outputs(self) -> AnyDict:
|
|
588
598
|
return {ref.name: self.get_object(ref.hash) for ref in self._outputs}
|
|
@@ -595,7 +605,7 @@ class RunSpan(Span):
|
|
|
595
605
|
label: str | None = None,
|
|
596
606
|
**attributes: JsonValue,
|
|
597
607
|
) -> None:
|
|
598
|
-
label = label or
|
|
608
|
+
label = label or clean_str(name)
|
|
599
609
|
hash_ = self.log_object(
|
|
600
610
|
value,
|
|
601
611
|
label=label,
|
|
@@ -698,7 +708,7 @@ class TaskSpan(Span, t.Generic[R]):
|
|
|
698
708
|
label: str | None = None,
|
|
699
709
|
**attributes: JsonValue,
|
|
700
710
|
) -> str:
|
|
701
|
-
label = label or
|
|
711
|
+
label = label or clean_str(name)
|
|
702
712
|
hash_ = self.run.log_object(
|
|
703
713
|
value,
|
|
704
714
|
label=label,
|
|
@@ -729,7 +739,7 @@ class TaskSpan(Span, t.Generic[R]):
|
|
|
729
739
|
label: str | None = None,
|
|
730
740
|
**attributes: JsonValue,
|
|
731
741
|
) -> str:
|
|
732
|
-
label = label or
|
|
742
|
+
label = label or clean_str(name)
|
|
733
743
|
hash_ = self.run.log_object(
|
|
734
744
|
value,
|
|
735
745
|
label=label,
|
|
@@ -753,7 +763,7 @@ class TaskSpan(Span, t.Generic[R]):
|
|
|
753
763
|
timestamp: datetime | None = None,
|
|
754
764
|
mode: MetricAggMode | None = None,
|
|
755
765
|
attributes: JsonDict | None = None,
|
|
756
|
-
) ->
|
|
766
|
+
) -> Metric: ...
|
|
757
767
|
|
|
758
768
|
@t.overload
|
|
759
769
|
def log_metric(
|
|
@@ -763,7 +773,7 @@ class TaskSpan(Span, t.Generic[R]):
|
|
|
763
773
|
*,
|
|
764
774
|
origin: t.Any | None = None,
|
|
765
775
|
mode: MetricAggMode | None = None,
|
|
766
|
-
) ->
|
|
776
|
+
) -> Metric: ...
|
|
767
777
|
|
|
768
778
|
def log_metric(
|
|
769
779
|
self,
|
|
@@ -775,7 +785,7 @@ class TaskSpan(Span, t.Generic[R]):
|
|
|
775
785
|
timestamp: datetime | None = None,
|
|
776
786
|
mode: MetricAggMode | None = None,
|
|
777
787
|
attributes: JsonDict | None = None,
|
|
778
|
-
) ->
|
|
788
|
+
) -> Metric:
|
|
779
789
|
metric = (
|
|
780
790
|
value
|
|
781
791
|
if isinstance(value, Metric)
|
|
@@ -784,27 +794,21 @@ class TaskSpan(Span, t.Generic[R]):
|
|
|
784
794
|
)
|
|
785
795
|
)
|
|
786
796
|
|
|
787
|
-
key =
|
|
788
|
-
|
|
789
|
-
if origin is not None:
|
|
790
|
-
origin_hash = self.run.log_object(
|
|
791
|
-
origin,
|
|
792
|
-
label=key,
|
|
793
|
-
event_name=EVENT_NAME_OBJECT_METRIC,
|
|
794
|
-
)
|
|
795
|
-
metric.attributes[METRIC_ATTRIBUTE_SOURCE_HASH] = origin_hash
|
|
796
|
-
|
|
797
|
-
metrics = self._metrics.setdefault(key, [])
|
|
798
|
-
if mode is not None:
|
|
799
|
-
metric = metric.apply_mode(mode, metrics)
|
|
800
|
-
metrics.append(metric)
|
|
797
|
+
key = clean_str(key)
|
|
801
798
|
|
|
802
799
|
# For every metric we log, also log it to the run
|
|
803
800
|
# with our `label` as a prefix.
|
|
804
801
|
#
|
|
805
|
-
#
|
|
802
|
+
# Let the run handle the origin and mode aggregation
|
|
803
|
+
# for us as we don't have access to the other times
|
|
804
|
+
# this task-metric was logged here.
|
|
805
|
+
|
|
806
806
|
if (run := current_run_span.get()) is not None:
|
|
807
|
-
run.log_metric(key, metric, prefix=self._label)
|
|
807
|
+
metric = run.log_metric(key, metric, prefix=self._label, origin=origin, mode=mode)
|
|
808
|
+
|
|
809
|
+
self._metrics.setdefault(key, []).append(metric)
|
|
810
|
+
|
|
811
|
+
return metric
|
|
808
812
|
|
|
809
813
|
def get_average_metric_value(self, key: str | None = None) -> float:
|
|
810
814
|
metrics = (
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import inspect
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
|
+
import re
|
|
7
8
|
import sys
|
|
8
9
|
import typing as t
|
|
9
10
|
from contextlib import contextmanager
|
|
@@ -27,6 +28,13 @@ logger = logging.getLogger("dreadnode")
|
|
|
27
28
|
add_non_user_code_prefix(Path(dreadnode.__file__).parent)
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
def clean_str(s: str) -> str:
|
|
32
|
+
"""
|
|
33
|
+
Clean a string by replacing all non-alphanumeric characters with underscores.
|
|
34
|
+
"""
|
|
35
|
+
return re.sub(r"[^\w/]+", "_", s.lower())
|
|
36
|
+
|
|
37
|
+
|
|
30
38
|
def safe_repr(obj: t.Any) -> str:
|
|
31
39
|
"""
|
|
32
40
|
Return some kind of non-empty string representation of an object, catching exceptions.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dreadnode"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.4"
|
|
4
4
|
description = "Dreadnode SDK"
|
|
5
5
|
requires-python = ">=3.10,<3.14"
|
|
6
6
|
|
|
7
7
|
[tool.poetry]
|
|
8
8
|
name = "dreadnode"
|
|
9
|
-
version = "1.0.
|
|
9
|
+
version = "1.0.4"
|
|
10
10
|
description = "Dreadnode SDK"
|
|
11
11
|
authors = ["Nick Landers <monoxgas@gmail.com>"]
|
|
12
12
|
repository = "https://github.com/dreadnode/sdk"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|