def test_resource_with_enum_in_schema_configured():
    from enum import Enum as PythonEnum

    class TestPythonEnum(PythonEnum):
        VALUE_ONE = 0
        OTHER = 1

    DagsterEnumType = Enum(
        "TestEnum",
        [
            EnumValue("VALUE_ONE", TestPythonEnum.VALUE_ONE),
            EnumValue("OTHER", TestPythonEnum.OTHER),
        ],
    )

    @resource(config_schema={"enum": DagsterEnumType})
    def enum_resource(context):
        return context.resource_config["enum"]

    @configured(enum_resource, {"enum": DagsterEnumType})
    def passthrough_to_enum_resource(config):
        return {"enum": "VALUE_ONE" if config["enum"] == TestPythonEnum.VALUE_ONE else "OTHER"}

    assert_pipeline_runs_with_resource(
        passthrough_to_enum_resource, {"enum": "VALUE_ONE"}, TestPythonEnum.VALUE_ONE
    )
Example #2
0
def shell_solid_config():
    return {
        'env': Field(
            Noneable(Permissive()),
            default_value=os.environ.copy(),
            is_required=False,
            description='An optional dict of environment variables to pass to the subprocess. '
            'Defaults to using os.environ.copy().',
        ),
        'output_logging': Field(
            Enum(
                name='OutputType',
                enum_values=[
                    EnumValue('STREAM', description='Stream script stdout/stderr.'),
                    EnumValue(
                        'BUFFER',
                        description='Buffer shell script stdout/stderr, then log upon completion.',
                    ),
                    EnumValue('NONE', description='No logging'),
                ],
            ),
            is_required=False,
            default_value='BUFFER',
        ),
        'cwd': Field(
            Noneable(str),
            default_value=None,
            is_required=False,
            description='Working directory in which to execute shell script',
        ),
    }
Example #3
0
def test_resource_with_enum_in_schema_configured():
    from enum import Enum as PythonEnum

    class TestPythonEnum(PythonEnum):
        VALUE_ONE = 0
        OTHER = 1

    DagsterEnumType = Enum(
        'TestEnum',
        [
            EnumValue('VALUE_ONE', TestPythonEnum.VALUE_ONE),
            EnumValue('OTHER', TestPythonEnum.OTHER),
        ],
    )

    @resource(config_schema={'enum': DagsterEnumType})
    def enum_resource(context):
        return context.resource_config['enum']

    @configured(enum_resource, {'enum': DagsterEnumType})
    def passthrough_to_enum_resource(config):
        return {
            'enum':
            'VALUE_ONE'
            if config['enum'] == TestPythonEnum.VALUE_ONE else 'OTHER'
        }

    assert_pipeline_runs_with_resource(passthrough_to_enum_resource,
                                       {'enum': 'VALUE_ONE'},
                                       TestPythonEnum.VALUE_ONE)
Example #4
0
def test_native_enum_dagster_enum():
    dagster_enum = Enum(
        'DagsterNativeEnum',
        [
            EnumValue(config_value='FOO', python_value=NativeEnum.FOO),
            EnumValue(config_value='BAR', python_value=NativeEnum.BAR),
        ],
    )

    called = {}

    @solid(config=dagster_enum)
    def dagster_enum_me(context):
        assert context.solid_config == NativeEnum.BAR
        called['yup'] = True

    pipeline_def = PipelineDefinition(name='native_enum_dagster_pipeline',
                                      solid_defs=[dagster_enum_me])

    result = execute_pipeline(
        pipeline_def, {'solids': {
            'dagster_enum_me': {
                'config': 'BAR'
            }
        }})
    assert result.success
    assert called['yup']
Example #5
0
def test_native_enum_dagster_enum():
    dagster_enum = Enum(
        "DagsterNativeEnum",
        [
            EnumValue(config_value="FOO", python_value=NativeEnum.FOO),
            EnumValue(config_value="BAR", python_value=NativeEnum.BAR),
        ],
    )

    called = {}

    @solid(config_schema=dagster_enum)
    def dagster_enum_me(context):
        assert context.solid_config == NativeEnum.BAR
        called["yup"] = True

    pipeline_def = PipelineDefinition(name="native_enum_dagster_pipeline",
                                      solid_defs=[dagster_enum_me])

    result = execute_pipeline(
        pipeline_def, {"solids": {
            "dagster_enum_me": {
                "config": "BAR"
            }
        }})
    assert result.success
    assert called["yup"]
Example #6
0
def shell_op_config():
    return {
        "env": Field(
            Noneable(Permissive()),
            is_required=False,
            description="An optional dict of environment variables to pass to the subprocess.",
        ),
        "output_logging": Field(
            Enum(
                name="OutputType",
                enum_values=[
                    EnumValue("STREAM", description="Stream script stdout/stderr."),
                    EnumValue(
                        "BUFFER",
                        description="Buffer shell script stdout/stderr, then log upon completion.",
                    ),
                    EnumValue("NONE", description="No logging"),
                ],
            ),
            is_required=False,
            default_value="BUFFER",
        ),
        "cwd": Field(
            Noneable(str),
            default_value=None,
            is_required=False,
            description="Working directory in which to execute shell script",
        ),
    }
Example #7
0
def test_logger_with_enum_in_schema_using_configured():
    from enum import Enum as PythonEnum

    class TestPythonEnum(PythonEnum):
        VALUE_ONE = 0
        OTHER = 1

    DagsterEnumType = Enum(
        "TestEnum",
        [
            EnumValue("VALUE_ONE", TestPythonEnum.VALUE_ONE),
            EnumValue("OTHER", TestPythonEnum.OTHER),
        ],
    )

    it = {}

    @logger(config_schema={"enum": DagsterEnumType})
    def test_logger(init_context):
        assert init_context.logger_config["enum"] == TestPythonEnum.OTHER
        it["ran test_logger"] = True

        logger_ = logging.Logger("test", level=coerce_valid_log_level("INFO"))
        return logger_

    @configured(test_logger, {"enum": DagsterEnumType})
    def pick_different_enum_value(config):
        it["ran pick_different_enum_value"] = True
        return {"enum": "OTHER" if config["enum"] == TestPythonEnum.VALUE_ONE else "VALUE_ONE"}

    assert_pipeline_runs_with_logger(pick_different_enum_value, {"enum": "VALUE_ONE"})

    assert it["ran test_logger"]
    assert it["ran pick_different_enum_value"]
Example #8
0
def pipeline_with_enum_config():
    @solid(
        config_schema=Enum(
            "TestEnum",
            [
                EnumValue(config_value="ENUM_VALUE_ONE", description="An enum value."),
                EnumValue(config_value="ENUM_VALUE_TWO", description="An enum value."),
                EnumValue(config_value="ENUM_VALUE_THREE", description="An enum value."),
            ],
        )
    )
    def takes_an_enum(_context):
        pass

    takes_an_enum()
Example #9
0
def pipeline_with_enum_config():
    @solid(
        config_schema=Enum(
            'TestEnum',
            [
                EnumValue(config_value='ENUM_VALUE_ONE', description='An enum value.'),
                EnumValue(config_value='ENUM_VALUE_TWO', description='An enum value.'),
                EnumValue(config_value='ENUM_VALUE_THREE', description='An enum value.'),
            ],
        )
    )
    def takes_an_enum(_context):
        pass

    return takes_an_enum()
Example #10
0
def test_enum_in_pipeline_execution():
    called = {}

    @solid(
        config_schema={"int_field": Int, "enum_field": Enum("AnEnum", [EnumValue("ENUM_VALUE")]),}
    )
    def config_me(context):
        assert context.solid_config["int_field"] == 2
        assert context.solid_config["enum_field"] == "ENUM_VALUE"
        called["yup"] = True

    pipeline_def = PipelineDefinition(name="enum_in_pipeline", solid_defs=[config_me])

    result = execute_pipeline(
        pipeline_def,
        {"solids": {"config_me": {"config": {"int_field": 2, "enum_field": "ENUM_VALUE"}}}},
    )

    assert result.success
    assert called["yup"]

    with pytest.raises(DagsterInvalidConfigError) as exc_info:
        execute_pipeline(
            pipeline_def,
            {"solids": {"config_me": {"config": {"int_field": 2, "enum_field": "NOPE"}}}},
        )

    assert (
        "Value at path root:solids:config_me:config:enum_field not in enum type AnEnum got NOPE"
        in str(exc_info.value)
    )
Example #11
0
def test_enum_in_pipeline_execution():
    called = {}

    @solid(
        config={'int_field': Int, 'enum_field': Enum('AnEnum', [EnumValue('ENUM_VALUE')]),}
    )
    def config_me(context):
        assert context.solid_config['int_field'] == 2
        assert context.solid_config['enum_field'] == 'ENUM_VALUE'
        called['yup'] = True

    pipeline_def = PipelineDefinition(name='enum_in_pipeline', solid_defs=[config_me])

    result = execute_pipeline(
        pipeline_def,
        {'solids': {'config_me': {'config': {'int_field': 2, 'enum_field': 'ENUM_VALUE'}}}},
    )

    assert result.success
    assert called['yup']

    with pytest.raises(DagsterInvalidConfigError) as exc_info:
        execute_pipeline(
            pipeline_def,
            {'solids': {'config_me': {'config': {'int_field': 2, 'enum_field': 'NOPE'}}}},
        )

    assert 'Error 1: Type failure at path "root:solids:config_me:config:enum_field"' in str(
        exc_info.value
    )
Example #12
0
def define_pipeline_with_enum_config():
    @solid(
        config_field=Field(
            Enum(
                'TestEnum',
                [
                    EnumValue(config_value='ENUM_VALUE_ONE', description='An enum value.'),
                    EnumValue(config_value='ENUM_VALUE_TWO', description='An enum value.'),
                    EnumValue(config_value='ENUM_VALUE_THREE', description='An enum value.'),
                ],
            )
        )
    )
    def takes_an_enum(_context):
        pass

    return PipelineDefinition(name='pipeline_with_enum_config', solids=[takes_an_enum])
Example #13
0
def test_enum_snap():
    enum_snap = snap_from_dagster_type(
        Enum(
            "CowboyType",
            [
                EnumValue("good"),
                EnumValue("bad"),
                EnumValue("ugly"),
            ],
        ))
    assert enum_snap.given_name == "CowboyType"
    assert enum_snap.key == "CowboyType"
    assert enum_snap.kind == ConfigTypeKind.ENUM
    assert enum_snap.enum_values == [
        ConfigEnumValueSnap(value, description=None)
        for value in ["good", "bad", "ugly"]
    ]
    assert enum_snap.fields is None
Example #14
0
def test_logger_with_enum_in_schema_using_configured():
    from enum import Enum as PythonEnum

    class TestPythonEnum(PythonEnum):
        VALUE_ONE = 0
        OTHER = 1

    DagsterEnumType = Enum(
        'TestEnum',
        [
            EnumValue('VALUE_ONE', TestPythonEnum.VALUE_ONE),
            EnumValue('OTHER', TestPythonEnum.OTHER),
        ],
    )

    it = {}

    @logger(config_schema={'enum': DagsterEnumType})
    def test_logger(init_context):
        assert init_context.logger_config['enum'] == TestPythonEnum.OTHER
        it['ran test_logger'] = True

        logger_ = logging.Logger('test', level=coerce_valid_log_level('INFO'))
        return logger_

    @configured(test_logger, {'enum': DagsterEnumType})
    def pick_different_enum_value(config):
        it['ran pick_different_enum_value'] = True
        return {
            'enum':
            'OTHER'
            if config['enum'] == TestPythonEnum.VALUE_ONE else 'VALUE_ONE'
        }

    assert_pipeline_runs_with_logger(pick_different_enum_value,
                                     {'enum': 'VALUE_ONE'})

    assert it['ran test_logger']
    assert it['ran pick_different_enum_value']
Example #15
0
def test_enum_in_pipeline_execution():
    called = {}

    @solid(
        config_field=Field(
            Dict(
                {
                    'int_field': Field(Int),
                    'enum_field': Field(Enum('AnEnum', [EnumValue('ENUM_VALUE')])),
                }
            )
        )
    )
    def config_me(info):
        assert info.config['int_field'] == 2
        assert info.config['enum_field'] == 'ENUM_VALUE'
        called['yup'] = True

    pipeline_def = PipelineDefinition(name='enum_in_pipeline', solids=[config_me])

    result = execute_pipeline(
        pipeline_def,
        {'solids': {'config_me': {'config': {'int_field': 2, 'enum_field': 'ENUM_VALUE'}}}},
    )

    assert result.success
    assert called['yup']

    with pytest.raises(PipelineConfigEvaluationError) as exc_info:
        execute_pipeline(
            pipeline_def,
            {'solids': {'config_me': {'config': {'int_field': 2, 'enum_field': 'NOPE'}}}},
        )

    assert 'Error 1: Type failure at path "root:solids:config_me:config:enum_field"' in str(
        exc_info.value
    )
def test_config_mapped_enum():
    from enum import Enum as PythonEnum

    class TestPythonEnum(PythonEnum):
        VALUE_ONE = 0
        OTHER = 1

    DagsterEnumType = Enum(
        "TestEnum",
        [
            EnumValue("VALUE_ONE", TestPythonEnum.VALUE_ONE),
            EnumValue("OTHER", TestPythonEnum.OTHER),
        ],
    )

    @solid(config_schema={"enum": DagsterEnumType})
    def return_enum(context):
        return context.solid_config["enum"]

    @composite_solid(
        config_schema={"num": int},
        config_fn=lambda cfg: {
            "return_enum": {
                "config": {
                    "enum": "VALUE_ONE" if cfg["num"] == 1 else "OTHER"
                }
            }
        },
    )
    def wrapping_return_enum():
        return return_enum()

    @pipeline
    def wrapping_return_enum_pipeline():
        wrapping_return_enum()

    assert (execute_pipeline(
        wrapping_return_enum_pipeline,
        {
            "solids": {
                "wrapping_return_enum": {
                    "config": {
                        "num": 1
                    }
                }
            }
        },
    ).output_for_solid("wrapping_return_enum") == TestPythonEnum.VALUE_ONE)

    assert (execute_pipeline(
        wrapping_return_enum_pipeline,
        {
            "solids": {
                "wrapping_return_enum": {
                    "config": {
                        "num": -11
                    }
                }
            }
        },
    ).output_for_solid("wrapping_return_enum") == TestPythonEnum.OTHER)

    @solid(config_schema={"num": int})
    def return_int(context):
        return context.solid_config["num"]

    @composite_solid(
        config_schema={"enum": DagsterEnumType},
        config_fn=lambda cfg: {
            "return_int": {
                "config": {
                    "num": 1 if cfg["enum"] == TestPythonEnum.VALUE_ONE else 2
                }
            }
        },
    )
    def wrap_return_int():
        return return_int()

    @pipeline
    def wrap_return_int_pipeline():
        wrap_return_int()

    assert (execute_pipeline(
        wrap_return_int_pipeline,
        {
            "solids": {
                "wrap_return_int": {
                    "config": {
                        "enum": "VALUE_ONE"
                    }
                }
            }
        },
    ).output_for_solid("wrap_return_int") == 1)

    assert (execute_pipeline(
        wrap_return_int_pipeline,
        {
            "solids": {
                "wrap_return_int": {
                    "config": {
                        "enum": "OTHER"
                    }
                }
            }
        },
    ).output_for_solid("wrap_return_int") == 2)
Example #17
0
def test_post_process_config():
    scalar_config_type = resolve_to_config_type(String)
    assert post_process_config(scalar_config_type, 'foo').value == 'foo'
    assert post_process_config(scalar_config_type, 3).value == 3
    assert post_process_config(scalar_config_type, {}).value == {}
    assert post_process_config(scalar_config_type, None).value is None

    enum_config_type = resolve_to_config_type(
        Enum('an_enum', [EnumValue('foo'),
                         EnumValue('bar', python_value=3)]))
    assert post_process_config(enum_config_type, 'foo').value == 'foo'
    assert post_process_config(enum_config_type, 'bar').value == 3
    assert ('config_value should be pre-validated'
            in post_process_config(enum_config_type, 'baz').errors[0].message)
    assert ('config_value should be pre-validated'
            in post_process_config(enum_config_type, None).errors[0].message)
    list_config_type = resolve_to_config_type([str])

    assert post_process_config(list_config_type, ['foo']).value == ['foo']
    assert post_process_config(list_config_type, None).value == []
    with pytest.raises(CheckError, match='Null array member not caught'):
        assert post_process_config(list_config_type, [None]).value == [None]

    nullable_list_config_type = resolve_to_config_type([Noneable(str)])
    assert post_process_config(nullable_list_config_type,
                               ['foo']).value == ['foo']
    assert post_process_config(nullable_list_config_type,
                               [None]).value == [None]
    assert post_process_config(nullable_list_config_type, None).value == []

    composite_config_type = resolve_to_config_type({
        'foo':
        String,
        'bar': {
            'baz': [str]
        },
        'quux':
        Field(str, is_required=False, default_value='zip'),
        'quiggle':
        Field(str, is_required=False),
    })

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        post_process_config(composite_config_type, {})

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        post_process_config(composite_config_type, {
            'bar': {
                'baz': ['giraffe']
            },
            'quux': 'nimble'
        })

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        post_process_config(composite_config_type, {
            'foo': 'zowie',
            'quux': 'nimble'
        })

    assert post_process_config(composite_config_type, {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'nimble'
    }).value == {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'nimble'
    }

    assert post_process_config(composite_config_type, {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        }
    }).value == {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'zip'
    }

    assert post_process_config(composite_config_type, {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quiggle': 'squiggle'
    }).value == {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'zip',
        'quiggle': 'squiggle'
    }

    nested_composite_config_type = resolve_to_config_type({
        'fruts': {
            'apple': Field(String),
            'banana': Field(String, is_required=False),
            'potato': Field(String, is_required=False, default_value='pie'),
        }
    })

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        post_process_config(nested_composite_config_type, {'fruts': None})

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        post_process_config(nested_composite_config_type,
                            {'fruts': {
                                'banana': 'good',
                                'potato': 'bad'
                            }})

    assert post_process_config(nested_composite_config_type, {
        'fruts': {
            'apple': 'strawberry'
        }
    }).value == {
        'fruts': {
            'apple': 'strawberry',
            'potato': 'pie'
        }
    }

    assert post_process_config(nested_composite_config_type, {
        'fruts': {
            'apple': 'a',
            'banana': 'b',
            'potato': 'c'
        }
    }).value == {
        'fruts': {
            'apple': 'a',
            'banana': 'b',
            'potato': 'c'
        }
    }

    any_config_type = resolve_to_config_type(Any)

    assert post_process_config(any_config_type, {
        'foo': 'bar'
    }).value == {
        'foo': 'bar'
    }

    assert post_process_config(
        ConfigType('gargle', given_name='bargle', kind=ConfigTypeKind.ANY), 3)

    selector_config_type = resolve_to_config_type(
        Selector({
            'one':
            Field(String),
            'another': {
                'foo': Field(String, default_value='bar', is_required=False)
            },
            'yet_another':
            Field(String, default_value='quux', is_required=False),
        }))

    with pytest.raises(CheckError):
        post_process_config(selector_config_type, 'one')

    with pytest.raises(ParameterCheckError):
        post_process_config(selector_config_type, None)

    with pytest.raises(ParameterCheckError,
                       match='Expected dict with single item'):
        post_process_config(selector_config_type, {})

    with pytest.raises(CheckError):
        post_process_config(selector_config_type, {
            'one': 'foo',
            'another': 'bar'
        })

    assert post_process_config(selector_config_type, {
        'one': 'foo'
    }).value == {
        'one': 'foo'
    }

    assert post_process_config(selector_config_type, {
        'one': None
    }).value == {
        'one': None
    }

    assert post_process_config(selector_config_type, {
        'one': {}
    }).value == {
        'one': {}
    }

    assert post_process_config(selector_config_type, {
        'another': {}
    }).value == {
        'another': {
            'foo': 'bar'
        }
    }

    singleton_selector_config_type = resolve_to_config_type(
        Selector(
            {'foo': Field(String, default_value='bar', is_required=False)}))

    assert post_process_config(singleton_selector_config_type, None).value == {
        'foo': 'bar'
    }

    permissive_dict_config_type = resolve_to_config_type(
        Permissive({
            'foo': Field(String),
            'bar': Field(String, default_value='baz', is_required=False)
        }))

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        post_process_config(permissive_dict_config_type, None)

    assert post_process_config(permissive_dict_config_type, {
        'foo': 'wow',
        'mau': 'mau'
    }).value == {
        'foo': 'wow',
        'bar': 'baz',
        'mau': 'mau',
    }
Example #18
0
'''NOTE: THIS FILE IS AUTO-GENERATED. DO NOT EDIT

@generated

Produced via:
python automation/parse_dataproc_configs.py \

'''

from dagster import Enum, EnumValue

State = Enum(
    name='State',
    enum_values=[
        EnumValue('STATE_UNSPECIFIED', description='Status is unspecified.'),
        EnumValue('NEW', description='Status is NEW.'),
        EnumValue('NEW_SAVING', description='Status is NEW_SAVING.'),
        EnumValue('SUBMITTED', description='Status is SUBMITTED.'),
        EnumValue('ACCEPTED', description='Status is ACCEPTED.'),
        EnumValue('RUNNING', description='Status is RUNNING.'),
        EnumValue('FINISHED', description='Status is FINISHED.'),
        EnumValue('FAILED', description='Status is FAILED.'),
        EnumValue('KILLED', description='Status is KILLED.'),
    ],
)

Substate = Enum(
    name='Substate',
    enum_values=[
        EnumValue('UNSPECIFIED', description='The job substate is unknown.'),
        EnumValue(
Example #19
0
from enum import Enum as PyEnum

from dagster import Enum, EnumValue

EbsVolumeType = Enum(
    name='EbsVolumeType', enum_values=[EnumValue('gp2'), EnumValue('io1'), EnumValue('standard')]
)


class EmrClusterState(PyEnum):
    Starting = 'STARTING'
    Bootstrapping = 'BOOTSTRAPPING'
    Running = 'RUNNING'
    Waiting = 'WAITING'
    Terminating = 'TERMINATING'
    Terminated = 'TERMINATED'
    TerminatedWithErrors = 'TERMINATED_WITH_ERRORS'


EmrActionOnFailure = Enum(
    name='EmrActionOnFailure',
    enum_values=[
        EnumValue('TERMINATE_JOB_FLOW'),
        EnumValue('TERMINATE_CLUSTER'),
        EnumValue('CANCEL_AND_WAIT'),
        EnumValue('CONTINUE'),
    ],
)

EmrAdjustmentType = Enum(
    name='EmrAdjustmentType',
Example #20
0
def test_apply_default_values():
    scalar_config_type = resolve_to_config_type(String)
    assert apply_default_values(scalar_config_type, 'foo') == 'foo'
    assert apply_default_values(scalar_config_type, 3) == 3
    assert apply_default_values(scalar_config_type, {}) == {}
    assert apply_default_values(scalar_config_type, None) is None

    enum_config_type = resolve_to_config_type(
        Enum('an_enum', [EnumValue('foo'),
                         EnumValue('bar', python_value=3)]))
    assert apply_default_values(enum_config_type, 'foo') == 'foo'
    assert apply_default_values(enum_config_type, 'bar') == 3
    with pytest.raises(CheckError,
                       match='config_value should be pre-validated'):
        apply_default_values(enum_config_type, 'baz')
    with pytest.raises(CheckError,
                       match='config_value should be pre-validated'):
        apply_default_values(enum_config_type, None)

    list_config_type = resolve_to_config_type(List[String])

    assert apply_default_values(list_config_type, ['foo']) == ['foo']
    assert apply_default_values(list_config_type, None) == []
    with pytest.raises(CheckError, match='Null list member not caught'):
        assert apply_default_values(list_config_type, [None]) == [None]

    nullable_list_config_type = resolve_to_config_type(List[Optional[String]])
    assert apply_default_values(nullable_list_config_type, ['foo']) == ['foo']
    assert apply_default_values(nullable_list_config_type, [None]) == [None]
    assert apply_default_values(nullable_list_config_type, None) == []

    composite_config_type = resolve_to_config_type(
        Dict({
            'foo': Field(String),
            'bar': Field(Dict({'baz': Field(List[String])})),
            'quux': Field(String, is_optional=True, default_value='zip'),
            'quiggle': Field(String, is_optional=True),
        }))

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        apply_default_values(composite_config_type, {})

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        apply_default_values(composite_config_type, {
            'bar': {
                'baz': ['giraffe']
            },
            'quux': 'nimble'
        })

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        apply_default_values(composite_config_type, {
            'foo': 'zowie',
            'quux': 'nimble'
        })

    assert apply_default_values(composite_config_type, {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'nimble'
    }) == {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'nimble'
    }

    assert apply_default_values(composite_config_type, {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        }
    }) == {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'zip'
    }

    assert apply_default_values(composite_config_type, {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quiggle': 'squiggle'
    }) == {
        'foo': 'zowie',
        'bar': {
            'baz': ['giraffe']
        },
        'quux': 'zip',
        'quiggle': 'squiggle'
    }

    nested_composite_config_type = resolve_to_config_type(
        Dict({
            'fruts':
            Field(
                Dict({
                    'apple':
                    Field(String),
                    'banana':
                    Field(String, is_optional=True),
                    'potato':
                    Field(String, is_optional=True, default_value='pie'),
                }))
        }))

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        apply_default_values(nested_composite_config_type, {'fruts': None})

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        apply_default_values(nested_composite_config_type,
                             {'fruts': {
                                 'banana': 'good',
                                 'potato': 'bad'
                             }})

    assert apply_default_values(nested_composite_config_type,
                                {'fruts': {
                                    'apple': 'strawberry'
                                }}) == {
                                    'fruts': {
                                        'apple': 'strawberry',
                                        'potato': 'pie'
                                    }
                                }

    assert apply_default_values(
        nested_composite_config_type,
        {'fruts': {
            'apple': 'a',
            'banana': 'b',
            'potato': 'c'
        }}) == {
            'fruts': {
                'apple': 'a',
                'banana': 'b',
                'potato': 'c'
            }
        }

    any_config_type = resolve_to_config_type(Any)

    assert apply_default_values(any_config_type, {'foo': 'bar'}) == {
        'foo': 'bar'
    }

    with pytest.raises(CheckError, match='Unsupported type'):
        assert apply_default_values(
            ConfigType('gargle', 'bargle', ConfigTypeKind.REGULAR), 3)

    selector_config_type = resolve_to_config_type(
        Selector({
            'one':
            Field(String),
            'another':
            Field(
                Dict({
                    'foo':
                    Field(String, default_value='bar', is_optional=True)
                })),
            'yet_another':
            Field(String, default_value='quux', is_optional=True),
        }))

    with pytest.raises(CheckError):
        apply_default_values(selector_config_type, 'one')

    with pytest.raises(ParameterCheckError):
        apply_default_values(selector_config_type, None)

    with pytest.raises(ParameterCheckError,
                       match='Expected dict with single item'):
        apply_default_values(selector_config_type, {})

    with pytest.raises(CheckError):
        apply_default_values(selector_config_type, {
            'one': 'foo',
            'another': 'bar'
        })

    assert apply_default_values(selector_config_type, {'one': 'foo'}) == {
        'one': 'foo'
    }

    assert apply_default_values(selector_config_type, {'one': None}) == {
        'one': None
    }

    assert apply_default_values(selector_config_type, {'one': {}}) == {
        'one': {}
    }

    assert apply_default_values(selector_config_type, {'another': {}}) == {
        'another': {
            'foo': 'bar'
        }
    }

    singleton_selector_config_type = resolve_to_config_type(
        Selector({'foo': Field(String, default_value='bar',
                               is_optional=True)}))

    assert apply_default_values(singleton_selector_config_type, None) == {
        'foo': 'bar'
    }

    permissive_dict_config_type = resolve_to_config_type(
        PermissiveDict({
            'foo':
            Field(String),
            'bar':
            Field(String, default_value='baz', is_optional=True)
        }))

    with pytest.raises(CheckError,
                       match='Missing non-optional composite member'):
        apply_default_values(permissive_dict_config_type, None)

    assert apply_default_values(permissive_dict_config_type, {
        'foo': 'wow',
        'mau': 'mau'
    }) == {
        'foo': 'wow',
        'bar': 'baz',
        'mau': 'mau',
    }
Example #21
0
from dagster import Enum, EnumValue

SparkDeployModeCluster = EnumValue('cluster')
SparkDeployModeClient = EnumValue('client')
SparkDeployMode = Enum(
    name='SparkDeployMode', enum_values=[SparkDeployModeCluster, SparkDeployModeClient]
)


class SparkSolidError(Exception):
    pass
Example #22
0
def bash_command_solid(bash_command, name=None, output_encoding=None):
    '''Execute a Bash command.
    '''
    check.str_param(bash_command, 'bash_command')
    name = check.opt_str_param(name, 'name', default='bash_solid')
    output_encoding = check.opt_str_param(output_encoding,
                                          'output_encoding',
                                          default='utf-8')

    @solid(
        name=name,
        config={
            'output_logging':
            Field(
                Enum(
                    'OutputType',
                    [
                        EnumValue('STREAM',
                                  description='Stream script stdout/stderr.'),
                        EnumValue(
                            'BUFFER',
                            description=
                            'Buffer bash script stdout/stderr, then log upon completion.',
                        ),
                        EnumValue('NONE', description='No logging'),
                    ],
                ),
                is_optional=True,
                default_value='STREAM',
            ),
            'env':
            Field(
                Permissive(),
                description=
                'Environment variables to pass to the child process; if not provided, '
                'the current process environment will be passed.',
                is_optional=True,
                default_value=None,
            ),
        },
    )
    def _bash_solid(context):
        '''This logic is ported from the Airflow BashOperator implementation.

        https://github.com/apache/airflow/blob/master/airflow/operators/bash_operator.py
        '''
        def log_info_msg(log_str):
            context.log.info('[bash][{name}] '.format(name=name) + log_str)

        tmp_path = seven.get_system_temp_directory()
        log_info_msg('using temporary directory: %s' % tmp_path)

        env = (context.solid_config['env'] if context.solid_config['env']
               is not None else os.environ.copy())

        with NamedTemporaryFile(dir=tmp_path, prefix=name) as tmp_file:
            tmp_file.write(bytes(bash_command.encode('utf-8')))
            tmp_file.flush()
            script_location = os.path.abspath(tmp_file.name)
            log_info_msg('Temporary script location: {location}'.format(
                location=script_location))

            def pre_exec():
                # Restore default signal disposition and invoke setsid
                for sig in ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ'):
                    if hasattr(signal, sig):
                        signal.signal(getattr(signal, sig), signal.SIG_DFL)
                os.setsid()

            log_info_msg(
                'Running command: {command}'.format(command=bash_command))

            # pylint: disable=subprocess-popen-preexec-fn
            sub_process = Popen(
                ['bash', tmp_file.name],
                stdout=PIPE,
                stderr=STDOUT,
                cwd=tmp_path,
                env=env,
                preexec_fn=pre_exec,
            )

            # Stream back logs as they are emitted
            if context.solid_config['output_logging'] == 'STREAM':
                line = ''
                for raw_line in iter(sub_process.stdout.readline, b''):
                    line = raw_line.decode(output_encoding).rstrip()
                    log_info_msg(line)

            sub_process.wait()

            # Collect and buffer all logs, then emit
            if context.solid_config['output_logging'] == 'BUFFER':
                line = ''
                for raw_line in iter(sub_process.stdout.readline, b''):
                    line += raw_line.decode(output_encoding)
                log_info_msg(line)

            # no logging in this case
            elif context.solid_config['output_logging'] == 'NONE':
                pass

            log_info_msg('Command exited with return code {retcode}'.format(
                retcode=sub_process.returncode))

            if sub_process.returncode:
                raise Failure(
                    description='[bash][{name}] Bash command failed'.format(
                        name=name))

        return line

    return _bash_solid
Example #23
0
    SchemaUpdateOption,
    SourceFormat,
    WriteDisposition,
)


class BigQueryLoadSource(PyEnum):
    DataFrame = "DATA_FRAME"
    GCS = "GCS"
    File = "FILE"


BQCreateDisposition = Enum(
    name="BQCreateDisposition",
    enum_values=[
        EnumValue(CreateDisposition.CREATE_IF_NEEDED),
        EnumValue(CreateDisposition.CREATE_NEVER),
    ],
)

BQPriority = Enum(
    name="BQPriority",
    enum_values=[
        EnumValue(QueryPriority.BATCH),
        EnumValue(QueryPriority.INTERACTIVE)
    ],
)

BQSchemaUpdateOption = Enum(
    name="BQSchemaUpdateOption",
    enum_values=[
Example #24
0
def define_test_enum_type():
    return ConfigEnum(name='TestEnum', enum_values=[EnumValue('VALUE_ONE')])
Example #25
0

@solid(
    config={
        'local_filepath':
        Field(str,
              is_required=True,
              description='local file path to get or put.'),
        'remote_filepath':
        Field(str,
              is_required=True,
              description='remote file path to get or put.'),
        'operation':
        Field(
            Enum('SFTPOperation',
                 [EnumValue('GET'), EnumValue('PUT')]),
            is_required=False,
            default_value='PUT',
            description='specify operation \'GET\' or \'PUT\', defaults to PUT',
        ),
        'confirm':
        Field(
            bool,
            is_required=False,
            default_value=True,
            description=
            'specify if the SFTP operation should be confirmed, defaults to True',
        ),
    },
    required_resource_keys={'ssh_resource'},
)
def test_config_mapped_enum():
    from enum import Enum as PythonEnum

    class TestPythonEnum(PythonEnum):
        VALUE_ONE = 0
        OTHER = 1

    DagsterEnumType = Enum(
        'TestEnum',
        [
            EnumValue('VALUE_ONE', TestPythonEnum.VALUE_ONE),
            EnumValue('OTHER', TestPythonEnum.OTHER),
        ],
    )

    @solid(config={'enum': DagsterEnumType})
    def return_enum(context):
        return context.solid_config['enum']

    @composite_solid(
        config={'num': int},
        config_fn=lambda _, cfg: {
            'return_enum': {'config': {'enum': 'VALUE_ONE' if cfg['num'] == 1 else 'OTHER'}}
        },
    )
    def wrapping_return_enum():
        return return_enum()

    @pipeline
    def wrapping_return_enum_pipeline():
        wrapping_return_enum()

    assert (
        execute_pipeline(
            wrapping_return_enum_pipeline,
            {'solids': {'wrapping_return_enum': {'config': {'num': 1}}}},
        ).output_for_solid('wrapping_return_enum')
        == TestPythonEnum.VALUE_ONE
    )

    assert (
        execute_pipeline(
            wrapping_return_enum_pipeline,
            {'solids': {'wrapping_return_enum': {'config': {'num': -11}}}},
        ).output_for_solid('wrapping_return_enum')
        == TestPythonEnum.OTHER
    )

    @solid(config={'num': int})
    def return_int(context):
        return context.solid_config['num']

    @composite_solid(
        config={'enum': DagsterEnumType},
        config_fn=lambda _, cfg: {
            'return_int': {'config': {'num': 1 if cfg['enum'] == TestPythonEnum.VALUE_ONE else 2}}
        },
    )
    def wrap_return_int():
        return return_int()

    @pipeline
    def wrap_return_int_pipeline():
        wrap_return_int()

    assert (
        execute_pipeline(
            wrap_return_int_pipeline,
            {'solids': {'wrap_return_int': {'config': {'enum': 'VALUE_ONE'}}}},
        ).output_for_solid('wrap_return_int')
        == 1
    )

    assert (
        execute_pipeline(
            wrap_return_int_pipeline,
            {'solids': {'wrap_return_int': {'config': {'enum': 'OTHER'}}}},
        ).output_for_solid('wrap_return_int')
        == 2
    )
Example #27
0
from dagster import Enum, EnumValue

SparkDeployModeCluster = EnumValue("cluster")
SparkDeployModeClient = EnumValue("client")
SparkDeployMode = Enum(
    name="SparkDeployMode",
    enum_values=[SparkDeployModeCluster, SparkDeployModeClient])


class SparkSolidError(Exception):
    pass


class SparkOpError(SparkSolidError):
    pass
Example #28
0
from enum import Enum as PyEnum

from dagster import Enum, EnumValue

EbsVolumeType = Enum(
    name='EbsVolumeType',
    enum_values=[EnumValue('gp2'),
                 EnumValue('io1'),
                 EnumValue('standard')])


class EmrClusterState(PyEnum):
    Starting = 'STARTING'
    Bootstrapping = 'BOOTSTRAPPING'
    Running = 'RUNNING'
    Waiting = 'WAITING'
    Terminating = 'TERMINATING'
    Terminated = 'TERMINATED'
    TerminatedWithErrors = 'TERMINATED_WITH_ERRORS'


EMR_CLUSTER_TERMINATED_STATES = [
    EmrClusterState.Terminating,
    EmrClusterState.Terminated,
    EmrClusterState.TerminatedWithErrors,
]

EMR_CLUSTER_DONE_STATES = EMR_CLUSTER_TERMINATED_STATES + [
    EmrClusterState.Waiting
]
Example #29
0
    PythonObjectDagsterType,
    String,
    dagster_type_loader,
    dagster_type_materializer,
)
from dagster.config.field_utils import Selector
from dagster.core.storage.system_storage import fs_intermediate_storage
from dagster.core.storage.type_storage import TypeStoragePlugin
from dagster.utils import dict_without_keys
from pyspark.sql import DataFrame as NativeSparkDataFrame

WriteModeOptions = Enum(
    "WriteMode",
    [
        EnumValue(
            "append", description="Append contents of this :class:`DataFrame` to existing data."
        ),
        EnumValue("overwrite", description="Overwrite existing data."),
        EnumValue("ignore", description="Silently ignore this operation if data already exists."),
        EnumValue(
            "error", description="(default case): Throw an exception if data already exists."
        ),
        EnumValue(
            "errorifexists",
            description="(default case): Throw an exception if data already exists.",
        ),
    ],
)


WriteCompressionTextOptions = Enum(
Example #30
0
    Permissive,
    Selector,
    Shape,
    String,
    TypeCheck,
    check,
    dagster_type_loader,
    dagster_type_materializer,
)

from .utils import DataFrameUtilities, apply_utilities_to_df

WriteCompressionTextOptions = Enum(
    "WriteCompressionText",
    [
        EnumValue("gzip"),
        EnumValue("bz2"),
        EnumValue("xz"),
    ],
)

EngineParquetOptions = Enum(
    "EngineParquet",
    [
        EnumValue("auto"),
        EnumValue("fastparquet"),
        EnumValue("pyarrow"),
    ],
)

DataFrameReadTypes = {