diff --git a/samples/sample_tap_google_analytics/ga_tap.py b/samples/sample_tap_google_analytics/ga_tap.py index 76fd952b2..2c4d3ee50 100644 --- a/samples/sample_tap_google_analytics/ga_tap.py +++ b/samples/sample_tap_google_analytics/ga_tap.py @@ -23,7 +23,9 @@ class SampleTapGoogleAnalytics(Tap): name: str = "sample-tap-google-analytics" config_jsonschema = PropertiesList( Property("view_id", StringType(), required=True), - Property("client_email", StringType(), required=True), + Property( + "client_email", StringType(), required=True, examples=["me@example.com"] + ), Property("private_key", StringType(), required=True, secret=True), ).to_dict() diff --git a/samples/sample_tap_sqlite/__init__.py b/samples/sample_tap_sqlite/__init__.py index 5f92b85d0..715839190 100644 --- a/samples/sample_tap_sqlite/__init__.py +++ b/samples/sample_tap_sqlite/__init__.py @@ -60,6 +60,7 @@ class SQLiteTap(SQLTap): DB_PATH_CONFIG, th.StringType, description="The path to your SQLite database file(s).", + examples=["./path/to/my.db", "/absolute/path/to/my.db"], ) ).to_dict() diff --git a/singer_sdk/typing.py b/singer_sdk/typing.py index d39072ac3..ba523a2d1 100644 --- a/singer_sdk/typing.py +++ b/singer_sdk/typing.py @@ -5,13 +5,16 @@ .. code-block:: python jsonschema = PropertiesList( + Property("username", StringType, required=True), + Property("password", StringType, required=True, secret=True), + Property("id", IntegerType, required=True), - Property("name", StringType), - Property("tags", ArrayType(StringType)), - Property("ratio", NumberType), + Property("foo_or_bar", StringType, allowed_values=["foo", "bar"]), + Property("ratio", NumberType, examples=[0.25, 0.75, 1.0]), Property("days_active", IntegerType), Property("updated_on", DateTimeType), Property("is_deleted", BooleanType), + Property( "author", ObjectType( @@ -19,6 +22,7 @@ Property("name", StringType), ) ), + Property("tags", ArrayType(StringType)), Property( "groups", ArrayType( @@ -42,7 +46,7 @@ from __future__ import annotations import sys -from typing import Generic, Mapping, TypeVar, Union, cast +from typing import Any, Generic, Mapping, TypeVar, Union, cast import sqlalchemy from jsonschema import validators @@ -356,8 +360,10 @@ def __init__( wrapped: W | type[W], required: bool = False, default: _JsonValue = None, - description: str = None, - secret: bool = False, + description: str | None = None, + secret: bool | None = False, + allowed_values: list[Any] | None = None, + examples: list[Any] | None = None, ) -> None: """Initialize Property object. @@ -374,6 +380,10 @@ def __init__( default: Default value in the JSON Schema. description: Long-text property description. secret: True if this is a credential or other secret. + allowed_values: A list of allowed value options, if only specific values + are permitted. This will define the type as an 'enum'. + examples: Optional. A list of one or more sample values. These may be + displayed to the user as hints of the expected format of inputs. """ self.name = name self.wrapped = wrapped @@ -381,6 +391,8 @@ def __init__( self.default = default self.description = description self.secret = secret + self.allowed_values = allowed_values or None + self.examples = examples or None @property def type_dict(self) -> dict: # type: ignore # OK: @classproperty vs @property @@ -423,6 +435,10 @@ def to_dict(self) -> dict: JSONSCHEMA_ANNOTATION_WRITEONLY: True, } ) + if self.allowed_values: + type_dict.update({"enum": self.allowed_values}) + if self.examples: + type_dict.update({"examples": self.examples}) return {self.name: type_dict} diff --git a/tests/core/test_jsonschema_helpers.py b/tests/core/test_jsonschema_helpers.py index 9b731af16..a23ba5813 100644 --- a/tests/core/test_jsonschema_helpers.py +++ b/tests/core/test_jsonschema_helpers.py @@ -365,6 +365,22 @@ def test_inbuilt_type(json_type: JSONTypeHelper, expected_json_schema: dict): }, {is_integer_type}, ), + ( + Property( + "my_prop9", + IntegerType, + allowed_values=[1, 2, 3, 4, 5, 6, 7, 8, 9], + examples=[1, 2, 3], + ), + { + "my_prop9": { + "type": ["integer", "null"], + "enum": [1, 2, 3, 4, 5, 6, 7, 8, 9], + "examples": [1, 2, 3], + } + }, + {is_integer_type}, + ), ], ) def test_property_creation(