Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

함수 입출력 자료형

함수 레지스트리에 게시할 TypeScript 함수는 모든 입력 매개변수와 반환값에 명시적인 타입이 필요합니다. Python도 지원하는 타입 주석으로 입력과 출력을 선언합니다. 로컬 언어가 표현할 수 있는 값 전체가 함수 경계에서 지원되는 것은 아닙니다.

레지스트리와 언어의 대응

레지스트리 타입TSv1TSv2Python
AttachmentAttachmentAttachmentAttachment
Booleanbooleanbooleanbool
Binary미지원미지원bytes
Byte미지원미지원Byte, 내부 int
Classification markingClassificationMarkingClassificationMarkingClassificationMarking
DateLocalDateDateISOStringDate 또는 datetime.date
Decimal미지원미지원decimal.Decimal
DoubleDoubleDoubleDouble, 내부 float
FloatFloatFloatFloat 또는 float
GeoPointGeoPointPointGeoPoint
GeoShapeGeoShapeGeometryGeoShape
GroupGroupGroupIdGroupId
IntegerIntegerIntegerInteger 또는 int
Interface시그니처 미지원Osdk.Instance<MyInterface>시그니처 미지원
Interface object set시그니처 미지원ObjectSet<MyInterface>시그니처 미지원
ListT[] 또는 Array<T>T[] 또는 Array<T>list[T]
LongLong, 내부 numberLong, 내부 stringLong, 내부 int
Mandatory markingMandatoryMarkingMandatoryMarkingMandatoryMarking
MapFunctionsMap<K, V>Record<K, V>dict[K, V]
Media referenceMediaItemMediaMedia
NotificationNotificationNotificationNotification
ObjectMyObjectTypeOsdk.Instance<MyObjectType>MyObjectType
Object setObjectSet<MyObjectType>ObjectSet<MyObjectType>MyObjectTypeObjectSet
Ontology editvoid 또는 비동기 Promise<void>Edits 목록OntologyEdit 목록
OptionalT | undefinedT | undefinedOptional[T] 또는 T | None
PrincipalPrincipalPrincipalPrincipal
RangeIRange<T>Range<T>Range[T]
SetSet<T>시그니처 미지원set[T]
Short미지원미지원Short, 내부 int
Stringstringstringstr
Struct/custom typeinterfaceinterfacedataclass 등 조건을 만족하는 클래스
TimestampTimestampTimestampISOStringTimestamp 또는 datetime.datetime
Two-dimensional aggregationTwoDimensionalAggregation<K, V>TwoDimensionalAggregation<K, V>TwoDimensionalAggregation[K, V]
Three-dimensional aggregationThreeDimensionalAggregation<K, S, V>ThreeDimensionalAggregation<K, S, V>ThreeDimensionalAggregation[K, S, V]
UserUserUserIdUserId

숫자 별칭은 TSv1의 @foundry/functions-api, TSv2의 @osdk/functions, Python의 functions.api에서 가져옵니다. TypeScript 함수 경계에서 raw number 대신 해당 별칭을 사용합니다. Python의 int는 Integer, float는 Float로 등록되므로 Long이나 Double이 필요하면 별칭을 명시해야 합니다.

숫자 범위와 정밀도

타입의미
Short-32,768부터 32,767까지의 정수
Integer-2³¹부터 2³¹-1까지의 정수
Long-(2⁵³-1)부터 2⁵³-1까지의 정수. 브라우저 호출에서 정밀도 손실을 피하는 안전 정수 범위입니다.
Float32비트 부동소수점
Double64비트 부동소수점
DecimalPython의 decimal.Decimal
BytePython int 기반의 별도 Byte 레지스트리 타입

입력뿐 아니라 반환 결과도 선언 타입의 범위에 맞아야 합니다. 덧셈이나 곱셈의 결과는 입력과 같은 타입의 범위를 넘을 수 있습니다.

TSv1의 기본 스칼라 함수는 다음과 같습니다. 합과 곱의 입력은 반환 범위 안의 결과를 만드는 값으로 사용합니다.

import { Double, Float, Function, Integer, Long, UserFacingError } from "@foundry/functions-api";

export class ScalarFunctions {
    @Function()
    public isEven(num: Integer): boolean { return num % 2 === 0; }

    @Function()
    public greet(name: string): string { return `Hello, ${name}!`; }

    @Function()
    public sum(a: Integer, b: Integer): Integer { return a + b; }

    @Function()
    public multiply(a: Float, b: Float): Float { return a * b; }

    @Function()
    public divide(a: Double, b: Double): Double {
        if (b === 0) throw new UserFacingError("0으로 나눌 수 없습니다.");
        return a / b;
    }

    @Function()
    public subtract(a: Long, b: Long): string {
        return (BigInt(a) - BigInt(b)).toString();
    }
}

TSv2는 함수별 파일의 default export로 정의합니다. Long은 문자열 별칭이므로 계산 전에 BigInt로 변환합니다. 두 안전 정수의 차이가 다시 안전 정수 범위 안이라는 보장은 없으므로 다음 예제는 정확한 차이를 문자열로 반환합니다.

import { Long } from "@osdk/functions";

export default function subtract(a: Long, b: Long): string {
    return (BigInt(a) - BigInt(b)).toString();
}

Python은 다음처럼 숫자 종류를 명시할 수 있습니다. first_ascii_byte는 ASCII 입력 예제이며 비ASCII 문자열은 encode에서 오류가 발생합니다. 일반 UTF-8 데이터는 encode_utf8의 Binary 반환을 사용합니다.

from decimal import Decimal
from functions.api import Byte, Double, Float, Integer, Long, Short, UserFacingError, function


@function
def is_even(num: Integer) -> bool:
    return num % 2 == 0


@function
def increment_short(num: Short) -> Short:
    return num + 1


@function
def multiply(a: Float, b: Float) -> Float:
    return a * b


@function
def divide(a: Double, b: Double) -> Double:
    if b == 0:
        raise UserFacingError("0으로 나눌 수 없습니다.")
    return a / b


@function
def subtract(a: Long, b: Long) -> str:
    return str(a - b)


@function
def return_pi() -> Decimal:
    return Decimal("3.1415926535")


@function
def encode_utf8(value: str) -> bytes:
    return value.encode("utf-8")


@function
def first_ascii_byte(value: str) -> Byte:
    if not value:
        raise UserFacingError("빈 문자열의 첫 바이트를 읽을 수 없습니다.")
    return value.encode("ascii")[0]

날짜와 시각

Date는 달력 날짜이고 Timestamp는 시간상의 한 시점입니다. TSv1은 LocalDate와 Timestamp 객체, TSv2는 각각 날짜 및 시각의 ISO 문자열 별칭, Python은 date와 datetime을 사용합니다.

값 만들기TSv1TSv2Python
예제 날짜 1999-10-17LocalDate.fromISOString("1999-10-17")DateISOString 타입의 "1999-10-17"date.fromisoformat("1999-10-17")
현재 시각Timestamp.now()TimestampISOString 타입의 new Date().toISOString()datetime.now(timezone.utc)

Python은 시간대가 있는 현재 시각을 반환하도록 작성할 수 있습니다.

from datetime import date, datetime, timezone
from functions.api import Date, Timestamp, function


@function
def return_date() -> Date:
    return date.fromisoformat("1999-10-17")


@function
def get_current_timestamp() -> Timestamp:
    return datetime.now(timezone.utc)

TSv2의 DateISOString과 TimestampISOString은 같은 문자열 기반이라도 레지스트리에서 서로 다른 타입으로 등록됩니다.

List, Set과 Map

컬렉션은 원소 타입을 명시해야 하며 그 타입도 지원 타입이어야 합니다. Map 키는 스칼라 또는 온톨로지 객체 타입으로 제한합니다.

배열에서 짝수만 남기는 TSv2 filterForEvenIntegers.ts의 예제입니다.

import { Integer } from "@osdk/functions";

export default function filterForEvenIntegers(nums: Integer[]): Integer[] {
    return nums.filter(num => num % 2 === 0);
}

TSv1은 같은 Integer[]와 filter를 사용하며 @Function 메서드로 정의합니다. Python은 return [num for num in nums if num % 2 == 0]을 list[Integer]로 반환합니다. TSv1 Set<Integer>의 크기는 mySet.size, Python set[Integer]의 크기는 len(my_set)으로 읽습니다. TSv2 함수 시그니처에는 Set을 사용할 수 없습니다.

문자열 맵의 표현은 다음과 같습니다. Phil과 Blue는 타입 구조를 보여 주는 예제 값입니다.

import { FunctionsMap } from "@foundry/functions-api";

const attributes = new FunctionsMap<string, string>();
attributes.set("Name", "Phil");
attributes.set("Favorite Color", "Blue");

TSv2는 Record<string, string>에 { "Name": "Phil", "Favorite Color": "Blue" }를 넣고 Python은 같은 값의 dict[str, str]를 사용합니다.

온톨로지 객체를 키로 사용

TSv1은 FunctionsMap<Airplane, Integer | undefined>, Python은 dict[Airplane, Integer | None]을 사용할 수 있습니다. 일반 JavaScript Map의 참조 동일성 문제는 객체 식별을 따릅니다.

TSv2는 객체 인스턴스가 아닌 해당 객체의 $objectSpecifier를 Record 키로 사용합니다.

import { ObjectSpecifier, Osdk } from "@osdk/client";
import { Integer } from "@osdk/functions";
import { Airplane } from "@ontology/sdk";

export default function getObjectMap(
    aircraft: Osdk.Instance<Airplane>[]
): Record<ObjectSpecifier<Airplane>, Integer | undefined> {
    const result: Record<ObjectSpecifier<Airplane>, Integer | undefined> = {};
    for (const airplane of aircraft) result[airplane.$objectSpecifier] = airplane.capacity;
    return result;
}

capacity가 없을 수 있음을 반환 값 타입에 유지한 가상 Airplane 예제입니다.

선택 값과 기본값

TypeScript 입력은 value?: T 또는 value: T | undefined, 반환은 T | undefined로 선언합니다. Python은 Optional[T] 또는 T | None을 사용하며 | None 문법에는 Python 3.10 이상이 필요합니다. T도 지원 타입이어야 합니다.

Python에서 None을 허용하는 것과 직접 호출 시 인수를 생략하는 것은 구분합니다. 생략도 허용하려면 기본값을 지정합니다.

from functions.api import function


@function
def greet(name: str | None = None) -> str | None:
    if name is None:
        return None
    return f"Hello, {name}!"

기본값을 가진 숫자 입력도 지원합니다. 다음은 가상의 Customer.baseRiskScore에 weight를 곱하는 예제 업무 계산이며 기본 weight는 0.75입니다.

import { Osdk } from "@osdk/client";
import { Double, UserFacingError } from "@osdk/functions";
import { Customer } from "@ontology/sdk";

export default function computeRiskFactor(customer: Osdk.Instance<Customer>, weight: Double = 0.75): Double {
    if (customer.baseRiskScore === undefined) throw new UserFacingError("기본 위험 점수가 없습니다.");
    return customer.baseRiskScore * weight;
}

TSv1도 메서드 입력의 weight: Double = 0.75, Python도 weight: Double = 0.75를 사용합니다. 기본값 자체가 빈 입력이나 계산 실패를 대신하는 값은 아니며 해당 입력을 생략했을 때 적용합니다.

사용자 지정 구조체

지원 타입을 필드로 조합한 사용자 타입을 함수 입력과 출력에 사용할 수 있으며 구조체 안에 다른 사용자 타입도 넣을 수 있습니다.

TypeScript는 interface로 정의하고 ? 또는 undefined 합집합으로 선택 필드를 만듭니다. Python 클래스는 모든 필드에 지원 타입 주석이 있어야 하며 __init__의 이름 있는 인수와 필드의 이름 및 타입이 일치해야 합니다. dataclass로 해당 생성자를 만들 수 있습니다.

from dataclasses import dataclass
from functions.api import Integer, function
from ontology_sdk.ontology.objects import Passenger


@dataclass
class PassengerInfo:
    name: str | None
    age: Integer | None


@function
def get_passenger_info(passenger: Passenger) -> PassengerInfo:
    return PassengerInfo(name=passenger.name, age=passenger.age)

TSv1과 TSv2의 대응 구조는 interface PassengerInfo { name?: string; age?: Integer; }입니다. 이 함수 입출력용 구조체와 온톨로지 구조체 속성의 생성 클래스는 다른 계약입니다. Python의 속성 편집에는 OSDK가 생성한 클래스를 사용해야 합니다.

집계와 범위

TwoDimensionalAggregation은 한 키에서 숫자로, ThreeDimensionalAggregation은 두 키에서 숫자로 매핑합니다. Workshop 차트 같은 소비자가 사용합니다.

버킷 키는 Boolean, String 또는 Range입니다. Range는 Integer와 Double 등 숫자 범위 및 Date와 Timestamp 범위에 사용할 수 있습니다.

표현TSv1TSv2Python
범위 필드min, maxstartValue, endValuemin, max
2차원{ buckets: [{ key, value }] }[{ key, value }]TwoDimensionalAggregation과 SingleBucket
3차원{ buckets: [{ key, value: [{ key, value }] }] }[{ key, groups: [{ key, value }] }]ThreeDimensionalAggregation과 NestedBucket, SingleBucket

범위의 한쪽 끝을 생략하면 열린 끝을 표현합니다. 집계의 숫자 또는 시간 구간에서는 시작을 포함하고 끝을 제외하는 그룹화 계약을 따릅니다.

가상의 부서 A와 월 구간 및 값 5.0을 TSv2 집계로 표현한 예입니다. 정적 예제 값이며 조회하는 함수는 사용자 지정 집계와 Python 집계를 따릅니다.

import { DateISOString, Double, Range, ThreeDimensionalAggregation } from "@osdk/functions";

const example: ThreeDimensionalAggregation<string, Range<DateISOString>, Double> = [{
    key: "A",
    groups: [{ key: { startValue: "2026-01-01", endValue: "2026-02-01" }, value: 5.0 }],
}];

Python은 같은 의미를 다음과 같이 구성합니다.

from datetime import date
from functions.api import Date, Double, NestedBucket, Range, SingleBucket, ThreeDimensionalAggregation

example: ThreeDimensionalAggregation[str, Range[Date], Double] = ThreeDimensionalAggregation(buckets=[
    NestedBucket(key="A", buckets=[
        SingleBucket(key=Range(min=date(2026, 1, 1), max=date(2026, 2, 1)), value=Double(5.0))
    ])
])

TSv1의 원격 그룹 집계는 이미 중첩 결과를 반환하지만 TSv2 aggregate의 평평한 행은 원하는 집계 구조로 조립해야 합니다.

객체와 객체 집합

유형을 먼저 프로젝트에 가져오고 해당 언어의 바인딩을 준비합니다. 단일 객체는 입력과 출력 모두 지원합니다. 가상의 Airplane.capacity가 선택 값이면 getCapacity의 반환도 Integer | undefined 또는 Python Integer | None으로 선언하거나 명시적으로 오류 처리해야 합니다.

객체 배열은 실행 시작 전에 객체를 로드합니다. 객체 집합은 필터, 링크 탐색과 집계를 정의하고 최종 결과를 요청할 때 로드하므로 대규모 입력에 적합합니다. 10,000개가 넘는 대상을 전달할 때도 전체 배열 로드를 피할 수 있지만 실제 로드 및 검색에는 별도 한도가 적용합니다.

언어capacity가 200보다 큰 객체 집합 반환
TSv1aircraft.filter(item => item.capacity.range().gt(200))
TSv2aircraft.where({ capacity: { $gt: 200 } })
Pythonaircraft.where(Airplane.object_type.capacity > 200)

입력과 출력 타입은 각각 ObjectSet<Airplane>, ObjectSet<Airplane>, AirplaneObjectSet입니다. 구체 객체를 모두 가져오지 않고 필터링된 집합을 다음 앱에 전달할 수 있습니다.

TSv2 구조체의 객체 참조

구조체나 구조체 목록의 필드에 Osdk.Instance 객체를 사용할 수 있습니다. 다음 가상 Ticket은 String 기본 키 ticketId와 flightNumber, passengerName, seat 속성을 가집니다. Airplane.flightNumber와 Passenger.name도 String이라고 가정합니다.

import { randomUUID } from "crypto";
import { Client, Osdk } from "@osdk/client";
import { Edits, createEditBatch, UserFacingError } from "@osdk/functions";
import { Airplane, Passenger, Ticket } from "@ontology/sdk";

interface TicketInfo {
    airplane?: Osdk.Instance<Airplane>;
    passenger?: Osdk.Instance<Passenger>;
    seat?: string;
}
type TicketEdit = Edits.Object<Ticket>;

export default function createTickets(client: Client, ticketInfo: TicketInfo[]): TicketEdit[] {
    const batch = createEditBatch<TicketEdit>(client);
    for (const info of ticketInfo) {
        if (info.airplane?.flightNumber === undefined || info.passenger?.name === undefined) {
            throw new UserFacingError("항공편 번호와 승객 이름이 있는 객체 참조가 필요합니다.");
        }
        batch.create(Ticket, {
            ticketId: randomUUID(), flightNumber: info.airplane.flightNumber,
            passengerName: info.passenger.name, seat: info.seat,
        });
    }
    return batch.getEdits();
}

인터페이스

TSv2는 온톨로지 인터페이스의 인스턴스와 객체 집합을 함수 입출력으로 지원합니다. TSv1과 Python의 함수 시그니처에서는 지원하지 않습니다. 객체 유형이 인터페이스를 구현하는 것과 함수 자체가 함수 인터페이스를 구현하는 것도 다른 개념입니다.

import { ObjectSet } from "@osdk/client";
import { Integer } from "@osdk/functions";
import { Person } from "@ontology/sdk";

export default function filterPeople(people: ObjectSet<Person>, minimumAge: Integer): ObjectSet<Person> {
    return people.where({ age: { $gt: minimumAge } });
}

온톨로지 편집 반환

일반 편집 함수에서 TSv1은 OntologyEditFunction과 void 또는 Promise<void>를 사용하며 런타임이 변경을 수집합니다. TSv2와 Python은 명시적인 편집 목록을 반환합니다. 적용 대기 쓰기는 별도 실행 모델이며 다른 지원 값을 반환할 수 있습니다.

예를 들어 직원의 lead 단일 링크를 바꿀 때는 외래 키를 가진 유형의 속성 편집을 선언합니다. 다대다 링크 선언을 그 관계에 그대로 적용하면 안 됩니다. 새 LaptopRequest를 함께 만든다면 해당 유형의 생성도 선언하고, 밀리초 시각 문자열 대신 충돌 가능성을 고려한 새 객체 키를 사용합니다. 구체 구현은 언어별 편집 API를 따릅니다.

보안 표지

MandatoryMarking은 보안 표지를 충족해야 접근할 수 있는 강제적 접근 통제에 사용합니다. ClassificationMarking은 민감한 정부 정보 등을 보호하는 보안 분류 기반 접근 제어(CBAC)의 표지입니다. 보안 표지 변경에는 액션의 권한 및 제출 조건이 적용됩니다.

다음 예제의 Employee에는 배열 속성 mandatoryMarkings와 classificationMarkings가 각각 해당 표지에 맞게 구성되어 있다고 가정합니다. 편집할 Employee 객체를 함수 인수로 받습니다.

TSv1은 같은 클래스에서 두 편집 함수를 정의할 수 있습니다.

import { Edits, OntologyEditFunction, MandatoryMarking, ClassificationMarking } from "@foundry/functions-api";
import { Employee } from "@foundry/ontology-api";

export class MarkingFunctions {
    @Edits(Employee)
    @OntologyEditFunction()
    public editMandatoryMarkings(employee: Employee, markings: MandatoryMarking[]): void {
        employee.mandatoryMarkings = markings;
    }

    @Edits(Employee)
    @OntologyEditFunction()
    public editClassificationMarkings(employee: Employee, markings: ClassificationMarking[]): void {
        employee.classificationMarkings = markings;
    }
}

TSv2는 주입한 Client로 배치를 만들고 객체를 수정합니다. 아래는 editMandatoryMarkings.ts이며 보안 분류 표지는 입력을 ClassificationMarking[]로, 속성을 classificationMarkings로 바꿔 같은 방식으로 구성합니다.

import { Client, Osdk } from "@osdk/client";
import { Edits, MandatoryMarking, createEditBatch } from "@osdk/functions";
import { Employee } from "@ontology/sdk";

export default function editMandatoryMarkings(
    client: Client, employee: Osdk.Instance<Employee>, markings: MandatoryMarking[]
): Edits.Object<Employee>[] {
    const batch = createEditBatch<Edits.Object<Employee>>(client);
    batch.update(employee, { mandatoryMarkings: markings });
    return batch.getEdits();
}

Python의 표지 속성은 Beta 지원을 활성화하고 생성 SDK의 Marking 값으로 변환합니다.

from foundry_sdk_runtime.markings import Marking
from functions.api import ClassificationMarking, MandatoryMarking, OntologyEdit, function
from ontology_sdk import FoundryClient
from ontology_sdk.ontology.objects import Employee


@function(beta=True, edits=[Employee])
def edit_mandatory_markings(employee: Employee, markings: list[MandatoryMarking]) -> list[OntologyEdit]:
    edits = FoundryClient().ontology.edits()
    edits.objects.Employee.edit(employee).mandatory_markings = [Marking(marking) for marking in markings]
    return edits.get_edits()


@function(beta=True, edits=[Employee])
def edit_classification_markings(employee: Employee, markings: list[ClassificationMarking]) -> list[OntologyEdit]:
    edits = FoundryClient().ontology.edits()
    edits.objects.Employee.edit(employee).classification_markings = [Marking(marking) for marking in markings]
    return edits.get_edits()

표지 ID 목록을 그대로 대입하면 런타임에 허용되더라도 LSP 경고가 생길 수 있어 생성 SDK의 Marking 표현을 사용합니다.

사용자, 그룹과 Principal

TSv1 User는 username을 가지며 firstName, lastName과 email은 없을 수 있습니다. Group은 name을 가집니다. 공통 Principal에는 id, realm과 attributes가 있으며 type이 user인지 group인지 검사합니다.

TSv2와 Python의 함수 경계에서는 UserId 또는 GroupId를 받으며 상세 정보는 관리자 API로 조회합니다. TSv2는 비동기 응답을 await해야 합니다.

import { Client } from "@osdk/client";
import { UserId } from "@osdk/functions";
import { Users } from "@osdk/foundry.admin";

export default async function getUserEmail(client: Client, userId: UserId): Promise<string | undefined> {
    const user = await Users.get(client, userId);
    return user.email;
}

Python은 함수의 런타임 인증을 사용하는 Platform SDK로 조회합니다.

from functions.api import GroupId, UserId, function
from foundry_sdk import FoundryClient


@function
def get_user_email(user_id: UserId) -> str | None:
    return FoundryClient().admin.User.get(user_id).email


@function
def get_group_name(group_id: GroupId) -> str:
    return FoundryClient().admin.Group.get(group_id).name

TSv2의 혼합 목록은 [{ type: "user", id: userId }, { type: "group", id: groupId }]를 Principal[]로 반환합니다. Python은 [Principal.user(user_id), Principal.group(group_id)]를 list[Principal]로 반환합니다. 실제 수신자 함수의 구현과 이름 필드 차이는 알림 구성을 따릅니다.

첨부 파일, 미디어와 알림

첨부 파일은 TSv1 readAsync의 Blob, TSv2 fetchContents의 Response, Python read의 BytesIO에서 내용을 읽습니다. 텍스트라면 각각 blob.text(), response.text(), bytes.decode("utf-8")로 읽으며 TSv2 Response의 성공 상태를 먼저 확인합니다.

미디어는 MediaReference를 감싼 Media 또는 TSv1 MediaItem으로 내용과 메타데이터를 읽고 문서 및 오디오 작업을 수행합니다. 함수 입력과 반환에 사용할 수 있습니다.

Notification은 플랫폼의 짧은 알림 및 이메일 본문과 링크를 반환합니다. 링크의 레이블과 대상은 URL, 온톨로지 객체 또는 Foundry 리소스 RID를 사용할 수 있습니다. 반환만으로 즉시 발송하는 호출은 아니며 소비 액션이 수신자와 전송을 구성합니다.

지리공간 자료형

GeoPoint는 위도와 경도의 점을, GeoShape는 Point, Polygon, LineString 등 유효한 GeoJSON Geometry를 표현합니다. 위치 배열은 GeoJSON 순서인 [경도, 위도]입니다. 다음 수치는 가상 좌표입니다.

언어점 생성
TSv1GeoPoint.fromCoordinates({ latitude: 37.7749, longitude: -22.4194 })
TSv2Point 타입의 { type: "Point", coordinates: [-22.4194, 37.7749] }
PythonGeoPoint(type="Point", coordinates=[-22.4194, 37.7749])

다각형 고리는 첫 좌표와 마지막 좌표를 같게 닫습니다. TSv2 Geometry의 예제입니다.

import { Geometry } from "@osdk/functions";

export default function createPolygon(): Geometry {
    return {
        type: "Polygon",
        coordinates: [[
            [-22.4, 37.8], [-22.5, 37.8], [-22.5, 37.7],
            [-22.4, 37.7], [-22.4, 37.8],
        ]],
    };
}

TSv1은 각 좌표를 GeoPoint.fromCoordinates로 만든 고리 배열에 Polygon.fromLinearRings([ring])를 사용합니다. Python은 Polygon(type="Polygon", coordinates=[ring])로 같은 좌표 배열을 전달합니다.

GeoJSON 문자열로 속성 수정

유효한 GeoJSON Geometry 문자열을 가상의 Region.boundary에 넣을 때 언어별 변환이 다릅니다.

언어변환
TSv1GeoShape.fromGeoJson(JSON.parse(boundary)). 먼저 문자열을 파싱합니다.
TSv2JSON.parse(boundary)로 만든 Geometry 객체를 편집 배치에 넣습니다.
Python기대하는 구체 클래스의 Polygon.from_geo_json(boundary)처럼 문자열 자체를 전달합니다. GeoShape에는 이 메서드가 없습니다.

TSv2의 as Geometry는 런타임 기하 검증이 아닙니다. boundary 입력은 유효한 Geometry JSON이라는 계약을 지켜야 하며 JSON 파싱 실패는 호출자에게 전파됩니다. Python에서 Polygon을 선택한 함수에는 다른 기하 유형을 넣지 않습니다.

from functions.api import OntologyEdit, Polygon, function
from ontology_sdk import FoundryClient
from ontology_sdk.ontology.objects import Region


@function(edits=[Region])
def update_boundary(region: Region, boundary: str) -> list[OntologyEdit]:
    edits = FoundryClient().ontology.edits()
    edits.objects.Region.edit(region).boundary = Polygon.from_geo_json(boundary)
    return edits.get_edits()

Pipeline Builder의 Python UDF는 행별 스칼라나 구조체 값을 반환하며 DataFrame을 반환하지 않습니다. 온톨로지 객체와 객체 집합 등은 UDF에서 지원하지 않는 타입이므로 함수 레지스트리 전체 지원표와 해당 소비 앱의 범위를 구분해야 합니다.