Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Jw/snow 1769565 add stage entity model #2027

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

sfc-gh-jwilkowski
Copy link

Pre-review checklist

  • I've confirmed that instructions included in README.md are still correct after my changes in the codebase.
  • I've added or updated automated unit tests to verify correctness of my new code.
  • I've added or updated integration tests to verify correctness of my new code.
  • I've confirmed that my changes are working by executing CLI's commands manually on MacOS.
  • I've confirmed that my changes are working by executing CLI's commands manually on Windows.
  • I've confirmed that my changes are up-to-date with the target branch.
  • I've described my changes in the release notes.
  • I've described my changes in the section below.

Changes description

https://snowflakecomputing.atlassian.net/browse/SNOW-1769565

Comment on lines +278 to +284
@app.command("createv2", requires_connection=True)
def stage_createv2(stage_name: FQN = StageNameArgument, **options) -> dict:
"""
needed only for testing purposes
"""
stage = StageEntity.create(stage_name.name)
return stage.to_dict()
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returning a dict is not supported, but that's what was printed by stage.to_dict()

hatch run snow stage createv2 jwilkowski_test2
{'created_on': datetime.datetime(2025, 1, 27, 14, 13, 24, 718000, tzinfo=TzInfo(UTC)),
 'directory_table': {'auto_refresh': False,
                     'enable': False,
                     'refresh_on_create': True},
 'has_credentials': False,
 'has_encryption_key': False,
 'kind': 'PERMANENT',
 'name': 'JWILKOWSKI_TEST2',
 'owner': 'ACCOUNTADMIN',
 'owner_role_type': 'ROLE',
 'type': 'stage',
 'url': ''}

Stage gets created on integration env:
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commands shout return CommandOutput subclass - check them in src/snowflake/cli/api/output/types.py
Currently stage create returns snowflake cursor with serverside-resposne

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StageCollection.create returns return StageResource(stage.name, self)- so just a MessageResult with stage.name should be ok

@sfc-gh-jsikorski sfc-gh-jsikorski marked this pull request as ready for review January 27, 2025 16:45
@sfc-gh-jsikorski sfc-gh-jsikorski requested a review from a team as a code owner January 27, 2025 16:45
Comment on lines +278 to +284
@app.command("createv2", requires_connection=True)
def stage_createv2(stage_name: FQN = StageNameArgument, **options) -> dict:
"""
needed only for testing purposes
"""
stage = StageEntity.create(stage_name.name)
return stage.to_dict()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commands shout return CommandOutput subclass - check them in src/snowflake/cli/api/output/types.py
Currently stage create returns snowflake cursor with serverside-resposne

type: Literal["stage"] = DiscriminatorField() # noqa: A003
# TODO: discuss: inherit or compose? composition would require either a lot of magic or double keying of fields,
# while inheritance does that for free + offers autocompletion etc
# api_resource: Stage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would go this way. So the model class will inherit only from EntityModelBase and use a field of type Stage with methods wrapping around it

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll give it a try

@staticmethod
def get_root() -> Root:
conn: SnowflakeConnection = get_cli_context().connection
return Root(conn)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this, after merge of #2014 EntityBase has snow_api_root property, that returns just that

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that's why I extracted that method for easier refactor once it's available upstream :)

entity_model_cls = cls.get_entity_model_type()
temp = stage_resource.fetch()

entity_model = entity_model_cls(type="stage", **temp.to_dict())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need adding discriminator field here. Also, we can call StageEntityModel directly- get_entity_model_type is rathe meant for use in situations, when we have many entities of different types

@@ -272,3 +273,12 @@ def _put(
auto_compress=auto_compress,
)
return QueryResult(cursor)


@app.command("createv2", requires_connection=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be safe for now, lets add hidden=True here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not intend to ship it in the final version, I just wanted to have some command for end to end testing. Is it expected to expose new commands? That would collide with existing ones

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but this will hide the command from any help messages, so the tests will pass

conn: SnowflakeConnection = get_cli_context().connection
if root is None:
root = cls.get_root()
return root.databases[conn.database].schemas[conn.schema].stages
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't have to be conn.database/schema - we should derive it from FQN if possible


# TODO: discuss: this code looks mostly generic so might go as well to the mixin class. Don't do it too fast to
# avoid issues of premature abstraction
@classmethod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could make it an instance method- so it would instantiate a model, as user defines a stage in the project, and then we would use instance method to create said stage server-side. WDYT?

Comment on lines +278 to +284
@app.command("createv2", requires_connection=True)
def stage_createv2(stage_name: FQN = StageNameArgument, **options) -> dict:
"""
needed only for testing purposes
"""
stage = StageEntity.create(stage_name.name)
return stage.to_dict()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StageCollection.create returns return StageResource(stage.name, self)- so just a MessageResult with stage.name should be ok

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants