What call translates a Task into an ordinary value...
# ask-community
h
What call translates a Task into an ordinary value? E.g. what translates a
Parameter
to a value in a
def
?
j
Hi @haf - the docs on parameters should help here: https://docs.prefect.io/core/concepts/parameters.html
h
They don't.
Sorry
I understand that something resolves
x
in that case, but not what.
What translates / resolves the value you pass into the
def
function?
On a higher level; how can I pass
PrefectSecrets
as values in a dict; why are simple values resolved but not nested?
Or maybe they are resolved? I just assumed they were not, since
Secret
instances were not.
j
Really not sure I understand your question here. Can you give an example of what you'd like to do?
h
I'm just trying to understand the magic that translates a Task instance into e.g. a
str
instance?
And why, for example, you should never pass
Task
instances to constructors, but only to
run
methods?
j
j
Hi haf, there's a lot of questions above, I'll answer a few of them, but it'd be good to be more precise about what you're having issues with (are you confused about how to use something? or experiencing an error/issue that you're trying to debug?).
What translates / resolves the value you pass into the
def
function?
I'm just trying to understand the magic that translates a Task instance into e.g. a
str
instance?
When you build a prefect
Flow
, you're describing a graph of tasks that you'd like to execute. The flow is composed of
Task
objects as nodes, with the edges expressing how task results pass through the workflow. When that flow is executed, prefect's internals walk that graph and pass results from task to task as described (this all happens in the `FlowRunner`/`TaskRunner` objects).
And why, for example, you should never pass
Task
instances to constructors, but only to
run
methods?
That only matters if you're not using
@task
based tasks (but instead using
Task
subclasses). If you're using class-based tasks, you need to break your
Task
initialization into two phases: • Static (non-task) arguments in the
Task
constructor. These are stored as attributes on the
Task
object itself. • Dynamic (task) arguments must be encoded as part of the flow graph. Usually this is done by calling
task.set_upstream
or
task.set_dependencies
, or calling the task directly like a function (
task(**dynamic_parameters_here)
). As I said above, this distinction only matters when using class-based tasks, if you're using
@task
to define tasks you won't have this issue.
On a higher level; how can I pass
PrefectSecrets
as values in a dict; why are simple values resolved but not nested?
Or maybe they are resolved? I just assumed they were not, since
Secret
instances were not.
It's hard for me to tell what you're asking here, but I think you're asking about the difference between
prefect.client.Secret
and
prefect.tasks.secrets.PrefectSecret
? The former is a client object, and shouldn't be treated as a task (you should have very few reasons to use this directly).
PrefectSecret
is what you usually want, and you should treat it as a
Task
. It can be passed as a parameter to other tasks.
h
Thanks @Jim Crist-Harif — thanks for trying to explain. I'll try to clarify what I mean: In my code, I have code like
clone = clone_repository(github_access_token, dbt_repository)
but despite the definition:
def clone_repository(token: str, repo: str):
the passed variables have types
PrefectSecret
and
Parameter
respectively. These are not strings; so how come I can pretend they are inside
clone_repository
?
j
Does
clone_repository
have a
@task
decorator?
h
Yes
Does that thing intercept the calls and store the values somewhere?
j
If it helps to think of it that way, then yes. Think of everything within a
with Flow(...)
block as describing code that will run later, but not now. Later when you call
flow.run
(or kick off a flow run from prefect cloud/server), the tasks you've defined are executed with the arguments as described.
šŸ™Œ 1
h
Thanks Jim!