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

feat: Add Posit product environment check helpers #391

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

Conversation

mconflitti-pbc
Copy link
Collaborator

Fixes #389

Copy link

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
1827 1715 94% 0% 🟢

New Files

File Coverage Status
src/posit/environment.py 100% 🟢
TOTAL 100% 🟢

Modified Files

File Coverage Status
src/posit/connect/_utils.py 78% 🟢
src/posit/connect/client.py 99% 🟢
src/posit/connect/external/databricks.py 91% 🟢
src/posit/connect/external/snowflake.py 91% 🟢
TOTAL 90% 🟢

updated for commit: 20457c4 by action🐍

Copy link
Collaborator

@tdstein tdstein left a comment

Choose a reason for hiding this comment

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

Everything looks good. Thanks for adding the deprecation warning! Ready to approve, but want to get your thoughts on runtime vs environment for the module name.

Comment on lines +1 to +30
from __future__ import annotations

import os


def get_product() -> str | None:
"""Returns the product name if called with a Posit product.

The products will always set the environment variable `POSIT_PRODUCT=<product-name>`
or `RSTUDIO_PRODUCT=<product-name>`.

RSTUDIO_PRODUCT is deprecated and acts as a fallback for backwards compatibility.
It is recommended to use POSIT_PRODUCT instead.
"""
return os.getenv("POSIT_PRODUCT") or os.getenv("RSTUDIO_PRODUCT")


def is_local() -> bool:
"""Returns true if called while running locally."""
return get_product() is None


def is_running_on_connect() -> bool:
"""Returns true if called from a piece of content running on a Connect server."""
return get_product() == "CONNECT"


def is_running_on_workbench() -> bool:
"""Returns true if called from within a Workbench server."""
return get_product() == "WORKBENCH"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need to support dynamic environment variables here? Another option is to use static variables.

from __future__ import annotations

import os

POSIT_PRODUCT = os.getenv("POSIT_PRODUCT") or os.getenv("RSTUDIO_PRODUCT")
IS_POSIT_CONNECT = POSIT_PRODUCT == "CONNECT"
IS_POSIT_WORKBENCH = POSIT_PRODUCT == "WORKBENCH"

Then from external.databricks/snowflake...

from .. import runtime

if not runtime.POSIT_PRODUCT:
    return;

Feel free to disregard this if you have already thought through it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this is great feedback. did not consider this.

i think i could go either way here. your approach is definitely simpler. let me ensure its testable. i would think just importing the module should trigger this to run but can check.

The connectapi and connectcreds equivalents are functions so followed suit but i like simple :)

Copy link
Collaborator

@dbkegley dbkegley Feb 26, 2025

Choose a reason for hiding this comment

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

I think this might be a little misleading for users today since workbench doesn't support this var yet.

I haven't tested this on workbench yet but I'm expecting to do something like this:

def is_workbench() -> bool:
"""Attempts to return true if called from a piece of content running on Posit Workbench.
There is not yet a definitive way to determine if the content is running on Workbench. This method is best-effort.
"""
return (
"RSW_LAUNCHER" in os.environ
or "RSTUDIO_MULTI_SESSION" in os.environ
or "RS_SERVER_ADDRESS" in os.environ
or "RS_SERVER_URL" in os.environ
)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think the functional approach is going to best here, especially from a testing perspective. Complicates things when the values are set upon import. Going to keep it functional.

@dbkegley yeah that is fine! can add these checks into the workbench runtime check

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@atheriel, do you have any thoughts here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Always the option punt and not have any workbench related check for now.

return os.getenv("POSIT_PRODUCT") or os.getenv("RSTUDIO_PRODUCT")


def is_local() -> bool:
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suppose is_local is a little subjective since their application could run elsewhere that isn't their machine or Posit.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

i like your suggestion above. will leave deprecation warning in utils is_local but can map it use the global vars.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

going to keep this since staying with functional approach

@mconflitti-pbc
Copy link
Collaborator Author

@zackverham and @dbkegley after looking at the existing is_local function, it was only checking if POSIT_PRODUCT is not set to CONNECT. So it would be considered local if running on workbench. Is that the intended effect?

@dbkegley
Copy link
Collaborator

@zackverham and @dbkegley after looking at the existing is_local function, it was only checking if POSIT_PRODUCT is not set to CONNECT. So it would be considered local if running on workbench. Is that the intended effect?

That was the intent initially but now that we need a better way to differentiate between Connect vs Workbench vs elsewhere the original implementation no longer seems correct.

@mconflitti-pbc
Copy link
Collaborator Author

@zackverham and @dbkegley after looking at the existing is_local function, it was only checking if POSIT_PRODUCT is not set to CONNECT. So it would be considered local if running on workbench. Is that the intended effect?

That was the intent initially but now that we need a better way to differentiate between Connect vs Workbench vs elsewhere the original implementation no longer seems correct.

Okay cool. This PR should address that then to ensure it is not connect nor workbench to be local.

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.

RSTUDIO_PRODUCT is deprecated; support POSIT_PRODUCT
3 participants