We’re having trouble using Blocks with SecretStr o...
# ask-community
l
We’re having trouble using Blocks with SecretStr on the latest prefect (2.14.5) with pydantic 2 (2.5.1). When I paste the example from the prefect docs into a ipython session, I get an error:
Copy code
from typing import Optional

from prefect.blocks.core import Block
from pydantic import SecretStr

class AWSCredentials(Block):
    aws_access_key_id: Optional[str] = None
    aws_secret_access_key: Optional[SecretStr] = None
    aws_session_token: Optional[str] = None
    profile_name: Optional[str] = None
    region_name: Optional[str] = None
Copy code
RuntimeError: no validator found for <class 'pydantic.types.SecretStr'>, see `arbitrary_types_allowed` in Config
Anyone have any ideas? I know pinning
pydantic<2
will make the error go away, but since Prefect supports pydantic 2 I’m trying to understand if this is a Prefect bug or if we need to do something differently with our blocks on pydantic 2.
1
a
Yep! From pydantic.v1 import SecretStr Until our deprecation window ends for v1, core prefect primitives will accept v2 objects as params (eg pass a v2 model to a flow works) but will be v1 subclasses (eg a block is a v1 BaseModel)
l
Thanks, let me give that a try
a
I saw @merlin had a similar Q a little bit ago so tagging them
thank you 1
l
If this code defining the block is going in a python package that is used to support projects on either pydantic 1 or 2, does this look right?
Copy code
from typing import Optional

from prefect.blocks.core import Block

try:
    from pydantic.v1 import SecretStr
except ImportError:
    from pydantic import SecretStr

class AWSCredentials(Block):
    aws_access_key_id: Optional[str] = None
    aws_secret_access_key: Optional[SecretStr] = None
    aws_session_token: Optional[str] = None
    profile_name: Optional[str] = None
    region_name: Optional[str] = None
a
Nah, since if someone has v2 installed it’ll import the v2 secret string, and then we’ll be back to square one What you want is: from pydantic.version import VERSION as PYDANTIC_VERSION HAS_PYDANTIC_V2 = PYDANTIC_VERSION.startswith("2.") if HAS_PYDANTIC_V2: From pydantic.1 Else: From pydantic Writing this from my phone so my bad so any formatting issues
gratitude thank you 1
l
Thanks I’ll give one of these a try and test it out. I think what I had above works too because it will try to import
pydantic.v1
and that will throw an import error if not on pydantic 2, but wasn’t sure if that was the best way to handle it
a
Oh sure, that makes sense! I misread the order of the import statements.
👍 1
109 Views