service-capacity-modeling 0.3.87__py3-none-any.whl → 0.3.89__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.
@@ -5,6 +5,7 @@ runtime-accessible docstrings.
5
5
 
6
6
  import ast
7
7
  import inspect
8
+ import sys
8
9
  from enum import Enum
9
10
  from functools import partial
10
11
  from operator import is_
@@ -16,6 +17,47 @@ from pydantic.json_schema import JsonSchemaValue
16
17
  from pydantic_core import CoreSchema
17
18
 
18
19
 
20
+ __all__ = ["StrEnum", "enum_docstrings"]
21
+
22
+ # StrEnum backport for Python 3.10 compatibility
23
+ # On Python 3.11+, use the stdlib version
24
+ if sys.version_info >= (3, 11):
25
+ from enum import StrEnum as StrEnum # pylint: disable=useless-import-alias
26
+ else:
27
+
28
+ class StrEnum(str, Enum):
29
+ """Backport of Python 3.11 StrEnum.
30
+
31
+ Provides consistent string behavior across all Python versions:
32
+ - f"{x}" returns the value (not "Foo.BAR")
33
+ - str(x) returns the value (not "Foo.BAR")
34
+ - x == "value" returns True (string comparison works)
35
+
36
+ This addresses PEP 663 which changed str(Enum) behavior in Python 3.11,
37
+ making (str, Enum) return "Foo.BAR" in f-strings instead of the value.
38
+ """
39
+
40
+ def __new__(cls, value: str, *args: Any, **kwargs: Any) -> "StrEnum":
41
+ if not isinstance(value, str):
42
+ raise TypeError(f"{value!r} is not a string")
43
+ member = str.__new__(cls, value)
44
+ member._value_ = value
45
+ return member
46
+
47
+ def __str__(self) -> str:
48
+ return str(self.value)
49
+
50
+ def __format__(self, format_spec: str) -> str:
51
+ # Ensures f-strings return value, not "Foo.BAR"
52
+ return str(self.value).__format__(format_spec)
53
+
54
+ @staticmethod
55
+ def _generate_next_value_(
56
+ name: str, start: int, count: int, last_values: list[str]
57
+ ) -> str:
58
+ return name.lower()
59
+
60
+
19
61
  E = TypeVar("E", bound=Enum)
20
62
 
21
63
 
@@ -4,7 +4,6 @@ from __future__ import annotations
4
4
  import re
5
5
  import sys
6
6
  from decimal import Decimal
7
- from enum import Enum
8
7
  from fractions import Fraction
9
8
  from functools import lru_cache
10
9
  from typing import Any
@@ -22,6 +21,7 @@ from pydantic import ConfigDict
22
21
  from pydantic import Field
23
22
 
24
23
  from service_capacity_modeling.enum_utils import enum_docstrings
24
+ from service_capacity_modeling.enum_utils import StrEnum
25
25
 
26
26
  GIB_IN_BYTES = 1024 * 1024 * 1024
27
27
  MIB_IN_BYTES = 1024 * 1024
@@ -46,16 +46,13 @@ class ExcludeUnsetModel(BaseModel):
46
46
 
47
47
 
48
48
  @enum_docstrings
49
- class IntervalModel(str, Enum):
49
+ class IntervalModel(StrEnum):
50
50
  """Statistical distribution models for approximating intervals
51
51
 
52
52
  When we have uncertainty intervals (low, mid, high), we need to choose
53
53
  a probability distribution to model that uncertainty for simulation purposes.
54
54
  """
55
55
 
56
- def __str__(self) -> str:
57
- return str(self.value)
58
-
59
56
  def __repr__(self) -> str:
60
57
  return f"D({self.value})"
61
58
 
@@ -204,7 +201,7 @@ def normalized_aws_size(name: str) -> Fraction:
204
201
  ###############################################################################
205
202
 
206
203
 
207
- class Lifecycle(str, Enum):
204
+ class Lifecycle(StrEnum):
208
205
  """Represents the lifecycle of hardware from initial preview
209
206
  to end-of-life.
210
207
 
@@ -223,7 +220,7 @@ class Lifecycle(str, Enum):
223
220
 
224
221
 
225
222
  @enum_docstrings
226
- class DriveType(str, Enum):
223
+ class DriveType(StrEnum):
227
224
  """Represents the type and attachment model of storage drives
228
225
 
229
226
  Drives can be either local (ephemeral, instance-attached) or network-attached
@@ -366,7 +363,7 @@ class Drive(ExcludeUnsetModel):
366
363
 
367
364
 
368
365
  @enum_docstrings
369
- class Platform(str, Enum):
366
+ class Platform(StrEnum):
370
367
  """Represents the CPU architecture or managed service platform
371
368
 
372
369
  Hardware can run on different CPU architectures (x86_64, ARM) or be a fully
@@ -617,7 +614,7 @@ class Pricing(ExcludeUnsetModel):
617
614
 
618
615
 
619
616
  @enum_docstrings
620
- class AccessPattern(str, Enum):
617
+ class AccessPattern(StrEnum):
621
618
  """The access pattern determines capacity planning priorities: latency-sensitive
622
619
  services target low P99 latency, while throughput-oriented services optimize
623
620
  for maximum requests per second.
@@ -633,7 +630,7 @@ class AccessPattern(str, Enum):
633
630
 
634
631
 
635
632
  @enum_docstrings
636
- class AccessConsistency(str, Enum):
633
+ class AccessConsistency(StrEnum):
637
634
  """
638
635
  Generally speaking consistency is expensive, so models need to know what
639
636
  kind of consistency will be required in order to estimate CPU usage
@@ -851,7 +848,7 @@ class CurrentClusters(ExcludeUnsetModel):
851
848
 
852
849
 
853
850
  @enum_docstrings
854
- class BufferComponent(str, Enum):
851
+ class BufferComponent(StrEnum):
855
852
  """Represents well known buffer components such as compute and storage
856
853
 
857
854
  Note that while these are common and defined here for models to share,
@@ -887,7 +884,7 @@ class BufferComponent(str, Enum):
887
884
 
888
885
 
889
886
  @enum_docstrings
890
- class BufferIntent(str, Enum):
887
+ class BufferIntent(StrEnum):
891
888
  """Defines the intent of buffer directives for capacity planning"""
892
889
 
893
890
  desired = "desired"
@@ -1,5 +1,4 @@
1
1
  from datetime import timedelta
2
- from enum import Enum
3
2
  from typing import Any
4
3
  from typing import Callable
5
4
  from typing import Dict
@@ -10,6 +9,7 @@ from pydantic import Field
10
9
 
11
10
  from .stateless_java import nflx_java_app_capacity_model
12
11
  from .stateless_java import NflxJavaAppArguments
12
+ from service_capacity_modeling.enum_utils import StrEnum
13
13
  from service_capacity_modeling.interface import AccessConsistency
14
14
  from service_capacity_modeling.interface import AccessPattern
15
15
  from service_capacity_modeling.interface import CapacityDesires
@@ -26,13 +26,13 @@ from service_capacity_modeling.interface import RegionContext
26
26
  from service_capacity_modeling.models import CapacityModel
27
27
 
28
28
 
29
- class NflxCounterCardinality(Enum):
29
+ class NflxCounterCardinality(StrEnum):
30
30
  low = "low"
31
31
  medium = "medium"
32
32
  high = "high"
33
33
 
34
34
 
35
- class NflxCounterMode(Enum):
35
+ class NflxCounterMode(StrEnum):
36
36
  best_effort = "best-effort"
37
37
  eventual = "eventual"
38
38
  exact = "exact"
@@ -95,7 +95,7 @@ class NflxCounterCapacityModel(CapacityModel):
95
95
  ) -> Tuple[Tuple[str, Callable[[CapacityDesires], CapacityDesires]], ...]:
96
96
  stores = []
97
97
 
98
- if extra_model_arguments["counter.mode"] == NflxCounterMode.best_effort.value:
98
+ if extra_model_arguments["counter.mode"] == NflxCounterMode.best_effort:
99
99
  stores.append(("org.netflix.evcache", lambda x: x))
100
100
  else:
101
101
  # Shared evcache cluster is used for eventual and exact counters
@@ -114,9 +114,9 @@ class NflxCounterCapacityModel(CapacityModel):
114
114
  # high cardinality : rollups happen once every 10 seconds
115
115
  # TODO: Account for read amplification from time slice configs
116
116
  # for better model accuracy
117
- if counter_cardinality == NflxCounterCardinality.low.value:
117
+ if counter_cardinality == NflxCounterCardinality.low:
118
118
  rollups_per_second = counter_deltas_per_second.scale(0.0167)
119
- elif counter_cardinality == NflxCounterCardinality.medium.value:
119
+ elif counter_cardinality == NflxCounterCardinality.medium:
120
120
  rollups_per_second = counter_deltas_per_second.scale(0.0333)
121
121
  else:
122
122
  rollups_per_second = counter_deltas_per_second.scale(0.1)
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  import math
3
- from enum import Enum
4
3
  from typing import Any
5
4
  from typing import Dict
6
5
  from typing import Optional
@@ -9,6 +8,7 @@ from typing import Tuple
9
8
  from pydantic import BaseModel
10
9
  from pydantic import Field
11
10
 
11
+ from service_capacity_modeling.enum_utils import StrEnum
12
12
  from service_capacity_modeling.interface import AccessConsistency
13
13
  from service_capacity_modeling.interface import AccessPattern
14
14
  from service_capacity_modeling.interface import Buffer
@@ -45,7 +45,7 @@ from service_capacity_modeling.stats import dist_for_interval
45
45
  logger = logging.getLogger(__name__)
46
46
 
47
47
 
48
- class Replication(str, Enum):
48
+ class Replication(StrEnum):
49
49
  none = "none"
50
50
  sets = "sets"
51
51
  evicts = "evicts"
@@ -1,6 +1,5 @@
1
1
  import logging
2
2
  import math
3
- from enum import Enum
4
3
  from typing import Any
5
4
  from typing import Dict
6
5
  from typing import Optional
@@ -9,6 +8,7 @@ from typing import Tuple
9
8
  from pydantic import BaseModel
10
9
  from pydantic import Field
11
10
 
11
+ from service_capacity_modeling.enum_utils import StrEnum
12
12
  from service_capacity_modeling.interface import AccessConsistency
13
13
  from service_capacity_modeling.interface import AccessPattern
14
14
  from service_capacity_modeling.interface import Buffer
@@ -45,7 +45,7 @@ from service_capacity_modeling.models.org.netflix.iso_date_math import iso_to_se
45
45
  logger = logging.getLogger(__name__)
46
46
 
47
47
 
48
- class ClusterType(str, Enum):
48
+ class ClusterType(StrEnum):
49
49
  strong = "strong"
50
50
  ha = "high-availability"
51
51
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: service-capacity-modeling
3
- Version: 0.3.87
3
+ Version: 0.3.89
4
4
  Summary: Contains utilities for modeling capacity for pluggable workloads
5
5
  Author: Joseph Lynch
6
6
  Author-email: josephl@netflix.com
@@ -1,7 +1,7 @@
1
1
  service_capacity_modeling/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  service_capacity_modeling/capacity_planner.py,sha256=JRagEFlg3u_zB1N5GzGsKAN55JZLad6p4IF_PmL8kcg,32780
3
- service_capacity_modeling/enum_utils.py,sha256=-jf9IkSg28B8ekXXel1l34FZw5iF525EttyiVft0MLg,3768
4
- service_capacity_modeling/interface.py,sha256=AV7QlogbCrdjl4nMQQhouyy-2_jNmngU6081NxEC5o4,42370
3
+ service_capacity_modeling/enum_utils.py,sha256=50Rw2kgYoJYCrybSbo9WaPPCWxlF5CyPCQtHxQ3kB18,5229
4
+ service_capacity_modeling/interface.py,sha256=mgX2qUsYf_rVxbYg1rFjRUH-QY11Z87mke4nWa1LwhM,42327
5
5
  service_capacity_modeling/stats.py,sha256=LCNUcQPfwF5hhIZwsfAsDe4ZbnuhDnl3vQHKfpK61Xc,6142
6
6
  service_capacity_modeling/hardware/__init__.py,sha256=P5ostvoSOMUqPODtepeFYb4qfTVH0E73mMFraP49rYU,9196
7
7
  service_capacity_modeling/hardware/profiles/__init__.py,sha256=7-y3JbCBkgzaAjFla2RIymREcImdZ51HTl3yn3vzoGw,1602
@@ -55,15 +55,15 @@ service_capacity_modeling/models/org/netflix/__init__.py,sha256=2Ld2NPxiO3vbYtOM
55
55
  service_capacity_modeling/models/org/netflix/aurora.py,sha256=Js33ZjxCtt34HiDPsWRT9mjKCAsnnCo9du15QArVFMo,13073
56
56
  service_capacity_modeling/models/org/netflix/cassandra.py,sha256=Fp37bHtWRJctJYYJhW78YbLeFXoX26QxREP_BMEItNE,39003
57
57
  service_capacity_modeling/models/org/netflix/control.py,sha256=wkJnqG7Nn7kQNcKEMzl9LFlA9xTAji2wYxL011VAKPI,5762
58
- service_capacity_modeling/models/org/netflix/counter.py,sha256=XopKlNMdvO5EbxAggn-KW_q7L3aKtXLXbry4ocl6i5Q,10494
58
+ service_capacity_modeling/models/org/netflix/counter.py,sha256=kTDL7dCnkn-XU27_Z1VBc4CCLCPoOqJZe9WgcENHHd4,10517
59
59
  service_capacity_modeling/models/org/netflix/crdb.py,sha256=iW7tyG8jpXhHIdXrw3DPYSHRAknPN42MlCRLJO4o9C8,20826
60
60
  service_capacity_modeling/models/org/netflix/ddb.py,sha256=9qRiuTqWev9zbYFFzewyowU7M41uALsuLklYx20yAXw,26502
61
61
  service_capacity_modeling/models/org/netflix/elasticsearch.py,sha256=zPrC6b2LNrAh3IWE3HCMUEYASacjYbHChbO4WZSMma4,25234
62
62
  service_capacity_modeling/models/org/netflix/entity.py,sha256=VHgEwnGtJAKlhvbE2kTif75OZmIsjjjoZrT6kb1LTgA,8750
63
- service_capacity_modeling/models/org/netflix/evcache.py,sha256=x8KwoULVpDm8UXLXEXfH8_zvoBDs8jSfOQLkaWKFcOg,25654
63
+ service_capacity_modeling/models/org/netflix/evcache.py,sha256=BDVRWely3F_3Ecb3Um3dQ024_I6XgvagpRJ6zdP5E18,25687
64
64
  service_capacity_modeling/models/org/netflix/graphkv.py,sha256=7ncEhx9lLsN_vGIKNHkvWfDdKffG7cYe91Wr-DB7IjU,8659
65
65
  service_capacity_modeling/models/org/netflix/iso_date_math.py,sha256=oC5sgIXDqwOp6-5z2bdTkm-bJLlnzhqcONI_tspHjac,1137
66
- service_capacity_modeling/models/org/netflix/kafka.py,sha256=JwiRsXOK5hYEr2YZL0SpHK2Z61PhbrItHXitAPdzty8,25514
66
+ service_capacity_modeling/models/org/netflix/kafka.py,sha256=1Ut1yBHgMCdH5chByuqBSmrZF-XpKdvFxAhRHaRV9nQ,25547
67
67
  service_capacity_modeling/models/org/netflix/key_value.py,sha256=WH8NblHqHwnAAumB2Zz1Qd4NBFWDQEQ1rpBcP3fVVQk,9409
68
68
  service_capacity_modeling/models/org/netflix/postgres.py,sha256=LBxDqkc-lYxDBu2VwNLuf2Q4o4hU3jPwu4YSt33Oe-8,4128
69
69
  service_capacity_modeling/models/org/netflix/rds.py,sha256=8GVmpMhTisZPdT-mP1Sx5U7VAF32lnTI27iYPfGg9CY,10930
@@ -77,9 +77,9 @@ service_capacity_modeling/tools/auto_shape.py,sha256=Jx9H2ay9-H_kUDjtB141owQNxGF
77
77
  service_capacity_modeling/tools/fetch_pricing.py,sha256=Qp-XMymkY1dvtyS51RufmEpfgOHv-IQ-XyzS8wp2-qM,4021
78
78
  service_capacity_modeling/tools/generate_missing.py,sha256=F7YqvMJAV4nZc20GNrlIsnQSF8_77sLgwYZqc5k4LDg,3099
79
79
  service_capacity_modeling/tools/instance_families.py,sha256=e5RuYkCLUITvsAazDH12B6KjX_PaBsv6Ne3mj0HK_sQ,9223
80
- service_capacity_modeling-0.3.87.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
81
- service_capacity_modeling-0.3.87.dist-info/METADATA,sha256=inokLEVxd6bZYZIVATdZpnvzEu-98z1teRHWVAVLEDU,10366
82
- service_capacity_modeling-0.3.87.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
83
- service_capacity_modeling-0.3.87.dist-info/entry_points.txt,sha256=ZsjzpG5SomWpT1zCE19n1uSXKH2gTI_yc33sdl0vmJg,146
84
- service_capacity_modeling-0.3.87.dist-info/top_level.txt,sha256=H8XjTCLgR3enHq5t3bIbxt9SeUkUT8HT_SDv2dgIT_A,26
85
- service_capacity_modeling-0.3.87.dist-info/RECORD,,
80
+ service_capacity_modeling-0.3.89.dist-info/licenses/LICENSE,sha256=nl_Lt5v9VvJ-5lWJDT4ddKAG-VZ-2IaLmbzpgYDz2hU,11343
81
+ service_capacity_modeling-0.3.89.dist-info/METADATA,sha256=ATxeW6sDZDkk4HQpmYGdmIlAXVXYj7zQaK5QJwkml8o,10366
82
+ service_capacity_modeling-0.3.89.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
83
+ service_capacity_modeling-0.3.89.dist-info/entry_points.txt,sha256=ZsjzpG5SomWpT1zCE19n1uSXKH2gTI_yc33sdl0vmJg,146
84
+ service_capacity_modeling-0.3.89.dist-info/top_level.txt,sha256=H8XjTCLgR3enHq5t3bIbxt9SeUkUT8HT_SDv2dgIT_A,26
85
+ service_capacity_modeling-0.3.89.dist-info/RECORD,,