Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions python/tk-core/_core_upgrader.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@

"""

import os
import sys
import stat
import datetime
import os
import shutil
import stat
import sys

LooseVersion = None
try:
Expand Down Expand Up @@ -99,7 +99,7 @@ def __current_version_less_than(log, sgtk_install_root, ver):
"""
log.debug("Checking if the currently installed version is less than %s..." % ver)

if __is_upgrade(sgtk_install_root) == False:
if not __is_upgrade(sgtk_install_root):
# there is no current version. So it is definitely
# not at least version X
log.debug(
Expand Down
25 changes: 25 additions & 0 deletions python/tk-core/codecov.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@

coverage:
status:
project:
default:
# Coverage checks are advisory only - never block CI
informational: true
# Only flag if overall project coverage drops below 80%
target: 80%
# Ignore drops of 1% or less (noise from small changes)
threshold: 1%
patch:
default:
# Coverage checks are advisory only - never block CI
informational: true
# Only flag if less than 80% of new/changed lines are covered
target: 80%

ignore:
# ignore generated QT files
- "**tank/authentication/ui/login_dialog.py"
- "**tank/authentication/ui/resources_rc.py"

# disable PySide6 code coverage for now
- "**tank/util/pyside6_patcher.py"

# flowam and other files not covered by unit tests
- "**tank/bootstrap/manager.py"
- "**tank/flowam/create.py"
- "**tank/flowam/host.py"
- "**tank/flowam/open.py"
- "**tank/flowam/utils.py"
- "**tank/platform/engine.py"
2 changes: 1 addition & 1 deletion python/tk-core/commit_id
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bc5f5e526d45baae95e2233f625550a31ccec92d
2fd64cd3f4f3f7f363c51ddf40f031605087107d
8 changes: 8 additions & 0 deletions python/tk-core/developer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ The `requirements/update_python_packages.py` script automates the creation and m
- Generate the `frozen_requirements.txt` file for consistency.
3. Validate that the `pkgs.zip` file contains all necessary packages and matches the updated requirements.

### Shared (Python-version-independent) vendor zips

In addition to the per-version `pkgs.zip`, `requirements/any/` holds pure-Python
packages that are safe to load across every supported Python version (e.g. the
Autodesk Flow Data Beta SDK). Each zip is auto-discovered by
`tank_vendor/__init__.py` and contains the importable package plus its
`.dist-info/` directory at the zip's root.

## How to upgrade ruamel.yaml

Until version `0.10.10`, the contents of the library was located at `tank_vendor/ruamel_yaml`.
Expand Down
26 changes: 15 additions & 11 deletions python/tk-core/developer/bake_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

# system imports
import os
import sys
import shutil
import sys

# add sgtk API
this_folder = os.path.abspath(os.path.dirname(__file__))
Expand All @@ -25,23 +25,27 @@
# any installed version in site-packages
sys.path.insert(0, python_folder)

import functools

# sgtk imports
from tank import LogManager
from tank.util import filesystem
from tank.descriptor import Descriptor, descriptor_uri_to_dict
from tank.descriptor import create_descriptor, is_descriptor_version_missing
from tank.descriptor.errors import TankDescriptorError
from tank.bootstrap import constants as bootstrap_constants
import functools

from tank.descriptor import (
Descriptor,
create_descriptor,
descriptor_uri_to_dict,
is_descriptor_version_missing,
)
from tank.descriptor.errors import TankDescriptorError
from tank.util import filesystem
from utils import (
cache_apps,
authenticate,
add_authentication_options,
OptionParserLineBreakingEpilog,
add_authentication_options,
authenticate,
automated_setup_documentation,
cache_apps,
cleanup_bundle_cache,
wipe_folder,
automated_setup_documentation,
)

# Set up logging
Expand Down
30 changes: 18 additions & 12 deletions python/tk-core/developer/build_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
a primed bundle cache.
"""

import datetime

# system imports
import os
import sys
import shutil
import datetime
import sys

# add sgtk API
this_folder = os.path.abspath(os.path.dirname(__file__))
Expand All @@ -31,22 +32,27 @@

# sgtk imports
from tank import LogManager
from tank.util import filesystem, sgre as re
from tank.errors import TankError
from tank.descriptor import Descriptor, descriptor_uri_to_dict, descriptor_dict_to_uri
from tank.descriptor import create_descriptor, is_descriptor_version_missing
from tank.bootstrap.baked_configuration import BakedConfiguration
from tank.bootstrap import constants as bootstrap_constants
from tank.bootstrap.baked_configuration import BakedConfiguration
from tank.descriptor import (
Descriptor,
create_descriptor,
descriptor_dict_to_uri,
descriptor_uri_to_dict,
is_descriptor_version_missing,
)
from tank.errors import TankError
from tank.util import filesystem
from tank.util import sgre as re
from tank_vendor import yaml

from utils import (
cache_apps,
authenticate,
add_authentication_options,
OptionParserLineBreakingEpilog,
add_authentication_options,
authenticate,
automated_setup_documentation,
cache_apps,
cleanup_bundle_cache,
wipe_folder,
automated_setup_documentation,
)

# set up logging
Expand Down
166 changes: 166 additions & 0 deletions python/tk-core/developer/find_flow_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#!/usr/bin/env python3
# Copyright (c) 2026 Shotgun Software Inc.
# CONFIDENTIAL AND PROPRIETARY
"""
Standalone CLI to find your Flow project ID using the Flow Data SDK.

Use this script to retrieve the Flow project ID for a given FPT project,
so it can be linked in the FPT site settings.

Defaults to production values. Override any individual setting via flags.

Usage:
# Production (default):
python scripts/find_flow_project.py

# Override just the endpoint (e.g. for staging):
python scripts/find_flow_project.py --endpoint <url>

# Override multiple values:
python scripts/find_flow_project.py --endpoint <url> --application-id <id> --auth-base-url <url>

# Filter by project name (case-insensitive):
python scripts/find_flow_project.py --name "My Project"
"""

from __future__ import annotations

import argparse
import os
import sys

# Set up sys.path so tk-core python packages are importable
_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
_REPO_ROOT = os.path.dirname(_SCRIPT_DIR)
sys.path.insert(0, os.path.join(_REPO_ROOT, "python"))

from tank.authentication.flow_auth._constants import (
DEFAULT_AUTH_APPLICATION_ID,
DEFAULT_AUTH_BASE_URL,
DEFAULT_AUTH_CALLBACK_URL,
REQUIRED_SCOPES,
)
from tank.util import LocalFileStorageManager
from tank_vendor.adsk_auth import AuthConfig, get_access_token
from tank_vendor.flow_data_sdk import GQLClient
from tank_vendor.flow_data_sdk.base import model as flow_model
from tank_vendor.flow_data_sdk.base.client import AuthenticationHandlerBase

DEFAULT_ENDPOINT = "https://medm-v2.medata-p-ue1.cloudos.autodesk.com/api/v2/graphql"

Check notice on line 49 in python/tk-core/developer/find_flow_project.py

View check run for this annotation

ShotGrid Chorus / privacy/bearer

internal_service.: https://medm-v2.medata-p-ue1.cloudos.autodesk.com/api/v2/graphql

This check is currently in beta. - Personal Data at Autodesk: https://share.autodesk.com/:b:/r/sites/LegalTopicsToolkits/Shared%20Documents/Personal%20Data%20at%20Autodesk.pdf - Data Privacy & Governance Policies at Autodesk: https://share.autodesk.com/sites/DPG/SitePages/Policies-%26-Guidelines.aspx


class TokenAuthHandler(AuthenticationHandlerBase):
"""Auth handler that returns a pre-fetched token."""

def __init__(self, token: str) -> None:
self._token = token

def get_authentication_token(self) -> str:
return self._token


def main() -> None:
parser = argparse.ArgumentParser(
description="List Flow collections/projects to find project IDs for FPT linking.",
)
parser.add_argument(
"--endpoint",
default=DEFAULT_ENDPOINT,
help=f"Flow GraphQL endpoint URL (default: {DEFAULT_ENDPOINT})",
)
parser.add_argument(
"--application-id",
default=DEFAULT_AUTH_APPLICATION_ID,
help="APS application ID (default: prod value)",
)
parser.add_argument(
"--auth-base-url",
default=DEFAULT_AUTH_BASE_URL,
help=f"APS auth base URL (default: {DEFAULT_AUTH_BASE_URL})",
)
parser.add_argument(
"--auth-callback-url",
default=DEFAULT_AUTH_CALLBACK_URL,
help=f"OAuth callback URL (default: {DEFAULT_AUTH_CALLBACK_URL})",
)
parser.add_argument(
"--name",
help="Only show projects whose name contains this string (case-insensitive)",
)
parser.add_argument(
"--force-reauth",
action="store_true",
help="Ignore cached tokens and force browser login",
)
parser.add_argument(
"--time-out",
type=float,
default=120.0,
help="Browser auth timeout in seconds (default: 120)",
)
args = parser.parse_args()

print(f"Endpoint : {args.endpoint}")
print("Authenticating... (browser may open if no valid cached token)")

auth_config = AuthConfig(
application_id=args.application_id,
base_url=args.auth_base_url,
callback_url=args.auth_callback_url,
description="Flow find project CLI",
required_application_scopes=REQUIRED_SCOPES,
storage_dir=LocalFileStorageManager.get_global_root(
LocalFileStorageManager.CACHE
),
)
token = get_access_token(
auth_config,
force_reauthentication=args.force_reauth,
time_out=args.time_out,
)

client = GQLClient(
endpoint=args.endpoint,
auth_handler=TokenAuthHandler(token),
)

name_filter = (args.name or "").strip().lower()
collections_resp = client.service_collection.collections(
flow_model.CollectionsInput()
).call()

collections = getattr(collections_resp, "collections", None) or []
if not collections:
print("No collections found for your account.")
sys.exit(0)

found_any = False
for col in collections:
col_id = getattr(col, "id", None) or ""
col_name = getattr(col, "name", None) or "(no name)"
projects_resp = client.service_project.projects_by_collection_id(
flow_model.ProjectsByCollectionIdInput(collection_id=col_id)
).call()
projects = getattr(projects_resp, "projects", None) or []
for proj in projects:
proj_name = getattr(proj, "name", None) or "(no name)"
proj_id = getattr(proj, "id", None) or ""
if name_filter and name_filter not in proj_name.lower():
continue
if not found_any:
print("\nCollection -> Project")
print("-" * 60)
found_any = True
print(f" {col_name} -> {proj_name}")
print(f" Project ID: {proj_id}")
print()
if not projects and not name_filter:
print(f" {col_name} -> (no projects)")

if not found_any and name_filter:
print(f"No project matching '{args.name}' found.")
sys.exit(1)


if __name__ == "__main__":
main()
12 changes: 5 additions & 7 deletions python/tk-core/developer/populate_bundle_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

# system imports
import os

import sys

# add sgtk API
Expand All @@ -30,16 +29,15 @@

# sgtk imports
from sgtk import LogManager
from sgtk.util import filesystem
from sgtk.descriptor import Descriptor, create_descriptor, is_descriptor_version_missing

from sgtk.util import filesystem
from utils import (
cache_apps,
authenticate,
add_authentication_options,
OptionParserLineBreakingEpilog,
cleanup_bundle_cache,
add_authentication_options,
authenticate,
automated_setup_documentation,
cache_apps,
cleanup_bundle_cache,
)

# set up logging
Expand Down
8 changes: 4 additions & 4 deletions python/tk-core/developer/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .caching import cache_apps, cleanup_bundle_cache, wipe_folder # noqa
from .option_parser import OptionParserLineBreakingEpilog # noqa
from .authentication import (
from .authentication import ( # noqa
add_authentication_options,
authenticate,
automated_setup_documentation,
) # noqa
)
from .caching import cache_apps, cleanup_bundle_cache, wipe_folder # noqa
from .option_parser import OptionParserLineBreakingEpilog # noqa
Loading