Skip to content

Latest commit

 

History

History
1508 lines (1042 loc) · 45.4 KB

CHANGELOG.md

File metadata and controls

1508 lines (1042 loc) · 45.4 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[3.10.6] - 2024-08-16

  • Fix: Cursor-based pagination also assumes "" is a terminal signal for pagination, same as if the next cursor were None.

[3.10.5] - 2024-08-16

  • Fix: Upgrade intermediate representation dependency to safely parse null unknown types.

[3.10.4] - 2024-08-14

  • Improvement: .dict performance is increased, consolidating to a single call to Pydantic's .dict instead of 2 in attempts to remove unset optional values.

[3.10.3] - 2024-08-14

  • Fix: Query encoding now appropriately takes arrays of deep objects into account.

[3.10.2] - 2024-08-13

  • Fix: Unions with utils now update forward refs again, a regression that was introduced in version 3.7.0

[3.10.1] - 2024-08-13

  • Fix: If there are no autogenerated examples present, the Python SDK generator no longer fails.

[3.10.0] - 2024-08-09

  • Feat: Adds a new flag to generate forward compatible Python enums, as opposed to leveraging raw string enums as literals. This works through addding an "_UNKNOWN" member to your enum set, the value of which is the raw value of the unrecognized enum.

    generators:
      - name: fernapi/fern-python-sdk
        config:
          pydantic_config:
            enum_type: "forward_compatible_python_enums" # Other valid option is: "literals" and "python_enums"

[3.9.0] - 2024-08-09

  • Feat: A new configuration is introduced to make discriminated union member naming more Pythonic. With V1 union naming, member names change from <UnionName>_<DiscriminantValue> to <DiscriminantValue><UnionName>. Concretely, union members previously named Chat_User will now be named UserChat under the new configuration.
    generators:
      - name: fernapi/fern-python-sdk
        config:
          pydantic_config:
            union_naming: "v1" # Other valid option is: "v0"

[3.8.0] - 2024-08-09

  • Improvement: generated SDKs now use ruff for linting and formatting, instead of Black.

[3.7.0] - 2024-08-08

  • Improvement: Python circular referencing types are more robust.

[3.6.0] - 2024-08-08

  • Feat: The generator now respects returning nested properties, these can be specified via:

    In OpenAPI below, we'd like to only return the property jobId from the Job object we get back from our server to our SDK users:

    my/endpoint:
      get:
        x-fern-sdk-return-value: jobId
        response: Job

    For a similar situation using the Fern definition:

    endpoints:
      getJob:
        method: GET
        path: my/endpoint
        response:
          type: Job
          property: jobId
  • Fix: The underlying content no longer sends empty JSON bodies, instead it'll pass a None value to httpx

[3.5.1] - 2024-08-05

  • Fix: The root type for unions with visitors now has it's parent typed correctly. This allows auto-complete to work once again on the union when it's nested within other pydantic models.

[3.5.0] - 2024-08-05

  • Improvement: The generated SDK now respects the pydantic version flag, generating V1 only code and V2 only code if specified. If not, the SDK is generated as it is today, with compatibility for BOTH Pydantic versions. This cleans up the generated code, and brings back features liked wrapped aliases for V1-only SDKs.

    Pydantic compatibility can be specified through the config below:

    generators:
      - name: fernapi/fern-python-sdk
        config:
          pydantic_config:
            version: "v1" # Other valid options include: "v2" and "both"

[3.4.2] - 2024-08-05

  • Fix: The Python generator now instantiates Any types as Optional[Any] to be able to meet some breaks in Pydantic V2.

[3.4.1] - 2024-08-04

  • Fix: Literal templates are generated if they are union members

[3.4.0] - 2024-08-02

  • Internal: The SDK generator has now been upgraded to use Pydantic V2 internally. Note that there is no change to the generated code, however by leveraging Pydantic V2 you should notice an improvement in fern generate times.

[3.3.4] - 2024-08-02

  • Improvement: Aliased literals are also defaulted within Pydantic models, whereas previously only direct literals were defaulted.
  • Improvement: Snippets now provide optional literals in functions and models.
  • Fix: Generated tests that expect an empty result when they are of type text (not JSON) now appropriately expect an empty string instead of None.

[3.3.3] - 2024-08-02

  • Fix: The generator now allows you to extend aliased types (as long as they're objects).

[3.3.2] - 2024-08-02

  • Fix: regression in readme generation introduced in 3.3.1

[3.3.1] - 2024-08-02

  • Fix: Generated READMEs now reference RequestOptions as TypedDicts correctly.

[3.3.0-rc1] - 2024-08-01

  • Fix: TypedDict snippets now include literals where available.

[3.3.0-rc0] - 2024-07-31

  • internal: Upgrade to IR 53.1.0
  • chore: The Python generator now creates snippet templates for undiscriminated unions.

[3.2.0-rc1] - 2024-07-29

  • Fix: The generated README now imports ApiError as if it were from outside the module.

[3.2.0-rc0] - 2024-07-25

  • Improvement: The Python SDK can now be generated such that inputs to requests are TypedDicts, instead of Pydantic models. This allows for consumers of the SDK to continue to have type hinting and autocomplete, but not need to import new object types when creating requests.

    With the following config:

    generators:
      - name: fernapi/fern-python-sdk
        config:
          pydantic_config:
            use_typeddict_requests: true

    The usage will change from:

    client\
        .imdb\
        .create_movie(
          request=CreateMovieRequest(title="title", rating=4.3),
        )

    to:

      client\
        .imdb\
        .create_movie(
          request={"title": "title", "rating": 4.3},
        )

[3.1.0-rc0] - 2024-07-24

  • Improvement: The root client users interact with is now exported from the main __init__.py, this allows users to access the client via from my_sdk import my_sdk_client as opposed to from my_sdk.client import my_sdk_client.
    • Note this comes with an edge-case break. In the unlikely event you have a type that conflicts in naming with the exported root client, that type model is post-fixed with "Model". e.g. a type Merge in an SDK exporting a client Merge becomes MergeModel.

[3.0.0-rc2] - 2024-07-24

  • Fix: update_forward_refs no longer raises errors, preserving original behavior, pre-3.x.

[3.0.0-rc1] - 2024-07-23

  • Fix: Sometimes mypy will error on the typing of expected_types within our test suite, despite them being labeled as typing.Any. This updates the types for tuples to typing.Tuple[tying.Any, typing.Any] to appease mypy.

[3.0.0-rc0] - 2024-07-23

  • Break: The generated SDK now supports Pydantic V2 outright, it no longer uses pydantic.v1 models. This change introduces additional breaks:
    • Wrapped aliases have been removed
    • Custom root validators for models with a root type have been removed (e.g. only unions with utils still leverages root models)
    • Public fields previously prefixed with _ are now prefixed with f_ (Pydantic V2 does not allow for _ prefixes on public fields and Python does not allow for a numeric prefix)

[2.16.0] - 2024-07-16

  • Improvement: The generated SDK now allows for specifying whether or not to generate streaming functions as overloaded functions or separate functions. Concretely, you can now specify whether or not you'd prefer the generation of your streaming functions as:

    def chat(...) -> ChatResponse:
      ...
    # and
    def chat_stream(...) -> typing.Iterator[StreamedChatResponse]:
      ...
    

    or:

    @overload
    def chat(...) -> ChatResponse:
      ...
    # and
    @overload
    def chat(..., stream=True) -> typing.Iterator[StreamedChatResponse]:
      ...
    

    The latter is configurable by specifying stream-condition and response-stream on your request within your Fern definition:

    service:
    auth: false
    base-path: /
    endpoints:
      listUsers:
        method: GET
        path: /users
        stream-condition: $request.stream
        request:
          name: ListUsersRequest
          query-parameters:
            page: integer
          body:
            properties:
              stream: optional<boolean>
        response: ListUsersResponse
        response-stream: User
    

[2.15.6] - 2024-07-17

  • Fix: The generated python SDK now requires an environment be specified if a default is not provided.

[2.15.5] - 2024-07-17

  • Fix: The generated python SDK Oauth client now no longer checks for an expiry when getting the access token if an expiry field is not configured.

[2.15.4] - 2024-07-10

  • Fix: The generated python SDK now serializes bytes within JSON as a utf-8 encoded string.

[2.15.3] - 2024-07-10

  • Fix: The generated python SDK no longer runs into a recursion error during snippet generation.

[2.15.2] - 2024-07-10

  • Fix: The generated python SDK no longer treats set as a reserved word for method names.

[2.15.1] - 2024-07-09

  • Fix: The unchecked base model no longer coerces None to a type.
  • Fix: The http client appropriately defaults empty fields within RequestOptions.

[2.15.0] - 2024-07-03

  • Improvement: The generated Python SDK can now respect configured defaults from the API spec.
generators:
  - name: fernapi/fern-python-sdk
    config:
      pydantic_config:
        use_provided_defaults: true

[2.14.1] - 2024-07-01

  • Fix: Sync and AsyncPage now pass through the generic type to BasePage, allowing the use of .items, etc. to be appropriately typed within your type checking system.

[2.14.0] - 2024-07-01

  • Fix: offset page now allows for the usage of 0 as a page start, previously the use of page or 1 made Python coerce booleans and become 1, ignoring the user-provided 0.

[2.14.0-rc3] - 2024-07-01

  • Improvement: Generated readmes now include an "advanced" section, outlining usage of retries, timeouts, error handling and usage of a custom client.

[2.14.0-rc2] - 2024-07-01

  • Improvement: Async snippets now run the async function leveraging asyncio.run to be more copy-pastable.

[2.14.0-rc1] - 2024-06-27

  • Fix: the fix from 2.5.2 is now case-insensitive Recap of 2.5.2: Fix: Support listSDK method names instead of defaulting tolist_.

[2.14.0-rc0] - 2024-06-26

  • Feat: the Python SDK now generates an accompanying SDK reference (reference.md) for users to review the SDK methods at a glance within the SDK's GitHub repository.

[2.13.1-rc0] - 2024-06-20

  • Fix: the Python SDK now does not send additional properties via JSON or data if the request is leveraging the other field.
  • Improvement: the Python SDK now copies unit tests over to the generated SDK for additional unit testing (separate from wire-format testing).

[2.13.0-rc0] - 2024-06-20

  • Upgrade: The Python SDK generator is now upgraded to IR V49.

[2.12.0-rc0] - 2024-06-25

  • Feature: README generation now supports a section dedicated to streaming usage, as well as one for paginated endpoints.

  • Improvement: Paginated endpoint snippets now show using an iterator:

    Before:

    from seed.client import SeedPagination
    
    client = SeedPagination(
        token="YOUR_TOKEN",
        base_url="https://yourhost.com/path/to/api",
    )
    client.users.list_with_cursor_pagination(
        page=1,
        per_page=1,
        order="asc",
        starting_after="string",
    )

    After:

    from seed.client import SeedPagination
    
    client = SeedPagination(
        token="YOUR_TOKEN",
        base_url="https://yourhost.com/path/to/api",
    )
    response = client.users.list_with_cursor_pagination(
        page=1,
        per_page=1,
        order="asc",
        starting_after="string",
    )
    for item in response:
        yield item
    # alternatively, you can paginate page-by-page
    for page in response.iter_pages():
        yield page

[2.11.0-rc0] - 2024-06-25

  • Improvement: The SDK now produces templates for the root clients within snippet-template.json. This allows users of the Templates API to pass in data for the auth variables present within the root client.

[2.10.2] - 2024-06-20

  • Fix: The SDK now handles stream termination sequences like [DONE]. This is a typical way for LLM providers to communicate when the stream has ended.

[2.10.1] - 2024-06-20

  • Fix: Improve the SDK to not leak JSONDecodeError to SDK users. Instead, an ApiError will be thrown with the text content of the response.

[2.10.0] - 2024-06-20

  • Feature: Add support for higher quality README.md generation.

[2.9.10] - 2024-06-20

  • Fix: the generator now only specifies the readme location within pyproject.toml if one was successfully created.

[2.9.9] - 2024-06-19

  • Internal: The generator now consumes IRv46.

[2.9.8] - 2024-06-18

  • Fix: The python generator only adds a publish step in github actions if credentials are specified.

[2.9.7] - 2024-06-12

  • Fix: The unchecked base model stops special casing defaults and pydantic v2.

[2.9.6] - 2024-06-11

  • Fix: Offset based pagination is now 1-based, as opposed to 0 based
  • Fix: The HTTP client now passes in additional body properties from the request options, even if the body is empty (regression from the client migration in 2.8.0)

[2.9.5] - 2024-06-10

  • Fix: Unions with elements that specify no properties are generated correctly.
  • Fix: Unions with a single type now have a valid type alias (rather than an invalid typing.Union).

[2.9.4] - 2024-06-07

  • Fix: The unchecked base model now handles pulling the discriminant from a dict, not just a model/object.

[2.9.3] - 2024-06-06

  • Fix: Snippet templates for discriminated unions now specify the template_input property which is required to actually see snippets of instantiating discriminated unions.

[2.9.2] - 2024-06-06

  • Fix: downgrades mypy so we can run it over all our files without concern for their pydantic bug
  • Fix: adds typehint to the response variable

[2.9.1] - 2024-06-06

  • Fix: The SDK removes unset query parameters from requests (regression from the client migration in 2.8.0)
  • Fix: The SDK fixes it's type for files parameters to the http client (regression from the client migration in 2.8.0)

[2.9.0] - 2024-06-05

  • Fix: Snippets preserve trailing slashes

[2.9.0-rc1] - 2024-06-05

  • Fix: The new http client abstraction ensures a slash is postfixed to the baseurl
  • Fix: Snippets preserve trailing slashes

[2.9.0-rc0] - 2024-06-04

  • Improvement: The Python generator now runs custom unit tests in CI if configured.

[2.8.2] - 2024-06-04

  • Fix: The none-filtering function now supports mypy's invariance check.

[2.8.1] - 2024-06-04

  • Fix: The parameter comment/documentation for timeouts on the root client now reflects the custom timeout passed through within configuration.

[2.8.0] - 2024-06-03

  • Improvement: Endpoint function request logic has been abstracted into the request function of the wrapped httpx client.

[2.7.0] - 2024-05-30

  • Improvement: The generator now outputs an exampleId alongside each generated snippet so that we can correlate snippets with the relevant examples. This is useful for retrieving examples from Fern's API and making sure that you can show multiple snippets in the generated docs.

[2.6.1] - 2024-05-31

  • Fix: this adds a back door token getter function to OAuth clients to better test the functionality.

[2.6.0] - 2024-05-30

  • Improvement: Support adding optional dependencies and extras to your generated pyproject.toml. To use this configuration, please add the following:

    extra_dependencies:
      boto3: 1.28.57
      langchain:
        version: "^0.1.20"
        optional: true
    extras:
      telemetry: ["langchain", "boto3"]

[2.5.7] - 2024-05-30

  • Fix: tests now carry a type annotation for expected_types variable.

[2.5.6] - 2024-05-29

  • Improvement: literal values are now all defaulted such that users are not required to plug in a redundant value.

[2.5.5] - 2024-05-29

  • Fix: Optional lists returned from pagination endpoints are now appropriately flattened such that the Pager return types are correctly Pager[ListItem] as opposed to Pager[List[ListItem]].

[2.5.4] - 2024-05-28

  • Fix: Add typing library for dateutils in testing lib to satisfy mypy errors.

[2.5.3] - 2024-05-24

  • Fix: Stop specifying custom licenses manually, let poetry handle adding them.

[2.5.2] - 2024-05-23

  • Fix: Support list SDK method names instead of defaulting to list_.

[2.5.1-rc0] - 2024-05-23

  • Fix: Literal parameters are added back to the request body.

[2.5.0-rc2] - 2024-05-23

  • Fix: Do not attempt to run fern test in CI until the command is more widely rolled out.

[2.5.0-rc1] - 2024-05-22

  • Fix: Address propogate -> propagate typo in python codegen.

[2.5.0-rc0] - 2024-05-22

  • Fix: This version addresses issues in unit test generation and reenables the creation of unit tests.

[2.4.0-rc0] - 2024-05-21

  • Fix: The Python SDK generator now uses safe names wherever string concat is not used (like in client generation naming), so this will update module and parameter names.

[2.3.4] - 2024-05-21

  • Fix: Snippets and unit tests now correctly write optional request bodies when inline_request_params is set to True. Previously the generator wrote snippets that inlined these parameters, which does not match the generated SDK itself.

[2.3.3] - 2024-05-21

  • Fix: Inlined body parameters now deconflict in naming with header and query parameters by prefixing the request objects name.

[2.3.2] - 2024-05-21

  • Fix: The pyproject.toml generator now writes authors in a valid format for tool.poetry, not just project

  • Fix: The query encoder now correctly handles none values

[2.3.1] - 2024-05-21

  • Fix: The pyproject.toml generator now includes project URLs when specified.

[2.3.0] - 2024-05-21

  • Improvement: Users can now specify information that will appear in their pypi record.
generators:
  - name: fernapi/fern-python-sdk
    metadata:
      description: this is the desc for my package
      keywords:
        - science
        - data analysis
      documentationLink: "https://buildwithfern.com/learn"
      homepageLink: "https://buildwithfern.com/"
      authors:
        - email: support@buildwithfern.com
          name: Armando

[2.2.2] - 2024-05-20

  • Fix: Inline request parameters now deconflict in naming with the unnamed path parameter arguments. Previously, when inlining request parameters into the method signature, we would not deconflict naming with the unnamed args preceding them. Now, conflicting unnamed parameters are post-fixed with an "_".

Before:

def method_name(id: str, *, id: str) -> None:
  ...

After:

def method_name(id_: str, *, id: str) -> None:
  ...

[2.2.1] - 2024-05-17

  • Internal: The generator now uses the latest FDR SDK.

[2.2.0] - 2024-05-16

  • Improvement: The generated SDK will now correctly encode deep object query parameters. For example, if you have an object {"test": {"nested": "object"}} as a query parameter, we will now encode it as test[nested]=object.

[2.1.1] - 2024-05-15

  • Chore: add enhanced snippet support for streaming endpoints.

    Before:

    from seed.client import SeedStreaming
    
    client = SeedStreaming(
        base_url="https://yourhost.com/path/to/api",
    )
    client.dummy.generate_stream(
        num_events=1,
    )

    After:

    from seed.client import SeedStreaming
    
    client = SeedStreaming(
        base_url="https://yourhost.com/path/to/api",
    )
    response = client.dummy.generate_stream(
        num_events=1,
    )
    for chunk in response:
        yield chunk

[2.1.0] - 2024-05-14

  • Feature: Add support for cursor and offset pagination.

    For example, consider the following endpoint /users endpoint:

    types:
      User:
        properties:
          name: string
    
      ListUserResponse:
        properties:
          next: optional<string>
          data: list<User>
    
    service:
      auth: false
      base-path: /users
      endpoints:
        list:
          path: ""
          method: GET
          pagination:
            cursor: $request.starting_after
            next_cursor: $response.next
            results: $response.data
          request:
            name: ListUsersRequest
            query-parameters:
              starting_after: optional<string>
          response: ListUsersResponse

    The generated client.Users.List can then be used as a User generator (effectively the "default"):

    for user in client.users.list(...):
      print user

    a page-by-page generator:

    for page in client.users.list(...).iter_pages():
      print(page.items)

    or statically calling next_page to perform the pagination manually:

    pager = client.users.list(...)
    # First page
    print(pager.items)
    # Second page
    pager = pager.next_page()
    print(pager.items)

[2.0.1] - 2024-05-14

  • Fix: the python generator previously used exclude_unset on pydantic models, however this would remove defaulted values. This change updates this to only exclude none fields that were not required.

[2.0.0] - 2024-05-09

  • Break: the python SDK is now on major version 2, there are no substantial logic changes, however default configuration has changed. To take this upgrade without any breaks, please add the below configuration to your generators.yml file:

    generators:
      - name: fernapi/fern-python-sdk
        config:
          inline_request_params: false

[1.7.0-rc0] - 2024-05-09

  • Improvement: you can now declare a new python version range for your pyproject.toml, which will declare a new version range for your pip package.

    generators:
      - name: fernapi/fern-python-sdk
        config:
          pyproject_python_version: ^3.8.1

[1.6.0-rc0] - 2024-05-09

  • Improvement: you can now specify dev dependencies from your generators.yml file:

    generators:
      - name: fernapi/fern-python-sdk
        config:
          extra_dev_dependencies:
            requests_mock: 1.12.1
            boto3: 1.28.57

    These will then populate your pyproject.toml automatically:

    ...
    [tool.poetry.dev-dependencies]
    requests_mock = "1.12.1"
    boto3 = "1.28.57"
    ...

[1.5.3-rc0] - 2024-05-02

  • Fix: the unchecked basemodel no longer tries to dereference an object if it's null.

[1.5.2-rc0] - 2024-05-02

  • Improvement: The python generator now produces sync snippet templates, as opposed to just async templates as it was before

[1.5.1-rc5] - 2024-05-01

  • Fix: Snippet templates now generate the correct imports for object types.

[1.5.1-rc4] - 2024-05-01

  • Fix: The SDK now generates discriminated union snippet templates correctly.

[1.5.1-rc3] - 2024-05-01

  • Improvement: Union types leverage the fern aware base model to include JSON and Dict function overrides.

[1.5.1-rc2] - 2024-05-01

  • Fix: The vanilla pydantic base model now respects the require_optional_fields, this became a regression in 1.5.1-rc0 when we started to inline union properties which leverages the vanilla base model.

[1.5.1-rc1] - 2024-05-01

  • Fix: Address formatting issues with snippet templates, we now strip newlines off OG snippets as well as plumb through indentation metadata to places that were previously missing it.

[1.5.1-rc0] - 2024-04-26

  • Fix: Discriminated union variants that are objects now have inlined properties instead of extending a base type.

    Circle_Shape(pydantic_v1.BaseModel):
      type: typing.Literal["circle"]
      radius: integer
    
    Square_Shape(pydantic_v1.BaseModel):
      type: typing.Literal["circle"]
      side: integer

    instead of

    Circle_Shape(Circle):
      type: typing.Literal["circle"]
    
    Square_Shape(Square):
      type: typing.Literal["circle"]

[1.5.0-rc0] - 2024-04-30

  • Feat: The generator now supports inlining top-level request parameters instead of requiring users create a request object.

    Config:

    generators:
      - name: fernapi/fern-python-sdk
        config:
          inline_request_params: true

    Before:

    def get_and_return_with_optional_field(
      self,
      *,
      request: ObjectWithOptionalField,
      request_options: typing.Optional[RequestOptions] = None
    ) -> ObjectWithOptionalField:
      ...

    After:

    def get_and_return_with_optional_field(
      self,
      *,
      string: typing.Optional[str] = OMIT,
      integer: typing.Optional[int] = OMIT,
      long: typing.Optional[int] = OMIT,
      double: typing.Optional[float] = OMIT,
      bool: typing.Optional[bool] = OMIT,
      request_options: typing.Optional[RequestOptions] = None
    ) -> ObjectWithOptionalField:
      ...

[1.4.0] - 2024-04-29

  • Improvement: keyword arguments are now ordered such that required params are ordered before optional params. Note that since these are kwargs, this is a non-breaking change.
  • Improvement: docstrings now match numpydoc/PEP257 format

[1.4.0-rc3] - 2024-04-24

  • Fix: Set mypy dev dependency in generated pyproject.toml to 1.9.0. This prevents upstream mypy bugs from affecting user builds. Note that this is only a dev dependency, so it does not affect the behavior of the SDK.
  • Fix: Temporarily disable unit test generation.
  • Improvement: Use named parameters for all httpx request params.

[1.4.0-rc2] - 2024-04-23

  • Fix: Initialize the OAuth token provider member variables to their default values before they are set.

[1.4.0-rc1] - 2024-04-22

  • Feature: The python SDK generator now supports OAuth client generation for the client-credentials flow.

[1.4.0-rc0] - 2024-04-22

  • Chore: default generated clients to follow redirects by default, this effectively flips the follow_redirects_by_default flag to True and can be reverted with the following configuration:

    generators:
      - name: fernapi/fern-python-sdk
        config:
          follow_redirects_by_default: false

[1.3.1-rc0] - 2024-04-22

  • Fix: the python SDK generator now checks to make sure a header is not null before casting it to a string.

[1.3.0-rc1] - 2024-04-22

  • Internal: add logging for python snippet template generation.

[1.3.0-rc0] - 2024-04-21

  • Beta, feature: The generator now registers snippet templates which can be used for dynamic SDK code snippet generation.

    Note: You must be on the enterprise tier to enable this mode.

[1.2.0-rc2] - 2024-04-10

  • Fix: The generator now correctly imports json when deserializing server sent events.

[1.2.0-rc0] - 2024-04-10

  • Feature: The generator now depends on v38 of Intermediate Representation which requires the latest CLI. As part of this, the generator now supports server sent events using httpx-sse.

[1.1.0-rc3] - 2024-04-04

  • Fix: There are a number of fixes to the skip validation code as well as tests to reflect those updates.

[1.1.0-rc2] - 2024-04-04

  • Fix: The generator now writes the skipped-validation cast with a suffixing new line so that the code compiles.

[1.1.0-rc1] - 2024-04-04

  • Fix: The generator no longer attempts to create a version file if Fern does not own generating the full package (e.g. in local generation). It's too confusing for to make the relevant changes to the package set up, and is also arguably not even needed in local generation.

[1.1.0-rc0] - 2024-04-03

  • [EXPERIMENTAL] Feature: The python SDK now includes a configuration option to skip pydantic validation. This ensures that Pydantic does not immediately fail if the model being returned from an API does not exactly match the Pydantic model. This is meant to add flexibility, should your SDK fall behind your API, but should be used sparingly, as the type-hinting for users will still reflect the Pydantic model exactly.

    generators:
      - name: fernapi/fern-python-sdk
        ...
        config:
          pydantic_config:
            skip_validation: true

[1.0.1] - 2024-04-03

  • Fix: Pydantic introduced a "break" to their 1.x libs by adding in a .v1 submodule that does not mirror the one that comes with pydantic v2. To get around this we now force the usage of the v1 submodule only if the pydantic version is v2.

[1.0.0] - 2024-04-02

  • Break: The python SDK now defaults new (breaking configuration) to introduce general improvements.

    In order to revert to the previous configuration flags and avoid the break, please leverage the below configuration:

    generators:
      - name: fernapi/fern-python-sdk
        config:
          improved_imports: false
          pydantic_config:
            require_optional_fields: true
            use_str_enums: false
            extra_fields: "forbid"
  • Improvement: The python SDK now supports specifying whether or not to follow redirects in requests by default, and exposes an option to override that functionality for consumers.

    generators:
      - name: fernapi/fern-python-sdk
        config:
          follow_redirects_by_default: true

    which then just instantiates the client like so:

    client = SeedExhaustive(
          token="YOUR_TOKEN",
          follow_redirects=True  # This is defaulted to the value passed into follow_redirects_by_default, and ignored if not specified
    )

[0.13.4] - 2024-04-03

  • Fix: revert the change from 0.13.2, the stream call returns a context manager, which is not awaited. The issue that this was meant to solve was actually fixed in version 0.12.2.

[0.13.3] - 2024-03-28

  • Fix: Github workflows for publishing now work again (previously the trigger was incorrect).

[0.13.2] - 2024-03-28

  • Fix: Asynchronous calls to httpx.stream are now awaited. This is applicable to any file download or JSON streaming (chat completion) endpoints.

    # Before
    async with httpx.stream
    
    # After
    async with await httpx.stream

[0.13.1] - 2024-03-26

  • Improvement: discriminant values in unions are now defaulted such that callers no longer need to specify the discriminant:

    # Before
    shape = Circle(discriminant="circle", radius=2.0)
    
    # After
    shape = Circle(radius=2.0)

[0.13.0] - 2024-03-25

  • Improvement: the python SDK now exposes it's version through __version__ to match module standards and expectations.
import seed

print(seed.__version__)  # prints 0.0.1 or whatever version is contained within the pyproject.toml

[0.12.5] - 2024-03-22

  • Fix: the python SDK uses the timeout provided to the top level client as the default per-request, previously if there was no timeout override in the RequestOptions, we'd default to 60s, even if a timeout was provided at the client level.

[0.12.4] - 2024-03-19

  • Improvement: Allow full forward compat with enums while keeping intellisense by unioning enum literals with typing.AnyStr.

    Before:

    Operand = typing.Union[typing.AnyStr, typing.Literal[">", "=", "less_than"]]

    After:

    Operand = typing.Literal[">", "=", "less_than"]

[0.12.3] - 2024-03-18

  • Improvement: Allow bytes requests to take in iterators of bytes, mirroring the types allowed by HTTPX.

[0.12.2] - 2024-03-18

  • Fix: Fix the returned type and value contained within the retrying wrapper for the HTTPX client (http_client.py).

[0.12.1] - 2024-03-14

  • Improves example generation and snippets for union types, as well as multi-url environments.
  • Fix: Stringifies header arguments, HTTPX was previously hard failing for certain types

[0.12.0] - 2024-03-11

  • Beta, feature: The SDK now generates tests leveraging auto-generated data to test typing, as well as wire-formatting (e.g. the SDKs are sending and receiving data as expected). This comes out of the box within the generated github workflow, as well as through the fern cli: fern test --command "your test command". Note: You must be on the enterprise tier to enable this mode.

[0.11.10] - 2024-03-08

  • feature: Expose a feature flag to pass through additional properties not specified within your pydantic model from your SDK. This allows for easier forward compatibility should your SDK drift behind your spec.

    Config:

    generators:
      - name: fernapi/fern-python-sdk
        ...
        config:
          pydantic_config:
            extra_fields: "allow"

    Example generated code:

    # my_object.py
    class MyObject(pydantic.BaseModel):
        string: typing.Optional[str] = None
        ...
    
    # main.py
    o = pydantic.parse_obj_as(MyObject, {"string": "string", "my_new_property": "custom_value"})
    
    print(o.my_new_property) # <--- "custom_value"

[0.11.9] - 2024-03-04

  • chore: Use docstrings instead of Pydantic field descriptions. This is meant to be a cleanliness change. This goes from:

    field: Optional[str] = pydantic.Field(default=None, description="This is the description.")

    to:

    field: Optional[str] = pydantic.Field(default=None)
    """This is the description."""

[0.11.8-rc1] - 2024-03-02

  • Beta, Improvement: Introduces a max_retries parameter to the RequestOptions dict accepted by all requests. This parameter will retry requests automatically, with exponential backoff and a jitter. The client will automatically retry requests of a 5XX status code, or certain 4XX codes (429, 408, 409).

      client\
        .imdb\
        .create_movie(
          request=CreateMovieRequest(title="title", rating=4.3),
          request_options={
            "max_retries": 5,
          }
        )

[0.11.8-rc0] - 2024-02-27

  • Beta: Introduce a client custom config that allows you to specify class_name and filename for the client. This configuration can be used in several ways:

    1. Rename your client class:

      config:
        client:
          class_name: Imdb
    2. Add custom functions to your generated SDK:

      config:
        client:
          class_name: BaseImdb
          filename: base_client.py
          exported_class_name: Imdb
          exported_filename: client.py

      Often times you may want to add additional methods or utilities to the generated client. The easiest way to do this is to configure Fern to write the autogenerated client in another file and extend it on your own.

      With the configuration above, Fern's Python SDK generator will create a class called BaseImdb and AsyncBaseImdb and put them in a file called base_client.py. As a user, you can extend both these classes with custom utilities.

      To make sure the code snippets in the generated SDK are accurate you can specify exported_class_name and exported_filename.

[0.11.7] - 2024-02-27

  • Improvement: Introduces a flag use_str_enums to swap from using proper Enum classes to using Literals to represent enums. This change allows for forward compatibility of enums, since the user will receive the string back.

    config:
      pydantic_config:
        use_str_enums: true
    

    generates enums as:

    Operand = typing.Literal[">", "=", "less_than"]
    

[0.11.6] - 2024-02-26

  • Improvement: You can now specify envvars to scan for headers, not just auth scheme headers.

    # OpenAPI
    x-fern-global-headers:
     - header: x-api-key
       name: api_key
       optional: true
       env: MY_API_KEY
    

    ... or ...

    # Fern Definition
    getAllUsers:
      method: GET
      path: /all
      request:
        name: GetAllUsersRequest
        headers:
          X-API-KEY: string
          env: MY_API_KEY
    

    the generated client will look like

    import os
    
    class Client:
    
      def __init__(self, *, apiKey: str = os.getenv("MY_API_KEY"))

[0.11.5] - 2024-02-23

  • Fix: Fix the usage of ApiError when leveraging auth envvars, when the schema for ApiError was changed, this usage was missed in the update.

[0.11.4] - 2024-02-23

  • Fix: We now grab enum values appropriately when enums are within unions.

[0.11.3] - 2024-02-22

  • Fix: Transition from lists to sequences within function calls, this is a fix as a result of how mypy handles type variance. This fix is only for function calls as testing shows that we do not hit the same issue within mypy with list[union[*]] fields on pydantic objects. This issue outlines it well: https://stackoverflow.com/questions/76138438/incompatible-types-in-assignment-expression-has-type-liststr-variable-has

  • Improvement: The Python SDK generator now defaults to require_optional_fields = False. This means that any requests that have optional fields no longer require a user to input data (or a None value) in. Example:

    # Previously:
    def my_function(my_parameter: typing.Optional[str]):
      pass
    
    my_function()  # <--- This fails mypy
    my_function(None)  # <--- This is necessary
    my_function("I work in both cases!")
    ...
    # Now:
    def my_function():
      pass
    
    my_function()  # <--- I no longer fail mypy
    my_function(None)  # <--- I still work
    my_function("I work in both cases!")

[0.11.2] - 2024-02-21

  • Improvement (Beta): The Python generator now supports a configuration option called improved_imports. To enable this configuration, just add the following to your generators.yml

    generators:
      - name: fernapi/fern-python-sdk
        ...
        config:
          improved_imports: true

    Enabling improved imports will remove the verbose resources directory in the SDK and make the imports shorter. This will also improve the imports from Pylance and Pyright that are automatically generated

    # Before
    from sdk.resources.fhir import Patient
    
    # After
    from sdk.fhir import Patient

[0.11.1] - 2024-02-20

  • Improvement: Python now supports specifying files to auto-export from the root __init__.py file, this means you can export custom classes and functions from your package for users to access like so:

    from my_package import custom_function

    the configuration for this is:

    # generators.yml
    python-sdk:
      generators:
        - name: fernapi/fern-python-sdk
          version: 0.11.1
          config:
            additional_init_exports:
              - from: file_with_custom_function
                imports:
                  - custom_function
  • Chore: Add a docstring for base clients to explain usage, example:

    class SeedTest:
      """
      Use this class to access the different functions within the SDK. You can instantiate any number of clients with different configuration that will propogate to these functions.
      ---
      from seed.client import SeedTest
    
      client = SeedTest(
          token="YOUR_TOKEN",
          base_url="https://yourhost.com/path/to/api",
      )
      """

[0.11.0] - 2024-02-19

  • Improvement: Python now supports a wider range of types for file upload, mirroring the httpx library used under the hood, these are grouped under a new type File:

    # core/file.py
    FileContent = typing.Union[typing.IO[bytes], bytes, str]
    File = typing.Union[
        # file (or bytes)
        FileContent,
        # (filename, file (or bytes))
        typing.Tuple[typing.Optional[str], FileContent],
        # (filename, file (or bytes), content_type)
        typing.Tuple[typing.Optional[str], FileContent, typing.Optional[str]],
        # (filename, file (or bytes), content_type, headers)
        typing.Tuple[typing.Optional[str], FileContent, typing.Optional[str], typing.Mapping[str, str]],
    ]
    
    ...
    
    # service.py
    def post(
        self,
        *,
        file: core.File,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Parameters:
            - file: core.File. See core.File for more documentation
            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        """
    ...
    
    # main.py
    f = open('report.xls', 'rb')
    service.post(file=f)
    
    # Or leveraging a tuple
    with open('largefile.zip', 'rb') as f:
      service.post(file=('largefile.zip', f))
    ...
  • Fix: Python now supports API specifications that leverage lists for file upload. Previously, Fern incorrectly made all list<file> type requests simply file.

    # service.py
    def post(
        self,
        *,
        file_list: typing.List[core.File],
        request_options: typing.Optional[RequestOptions] = None,
    ) -> None:
        """
        Parameters:
            - file_list: typing.List[core.File]. See core.File for more documentation
            - request_options: typing.Optional[RequestOptions]. Request-specific configuration.
        """
    ...
    
    # main.py
    f1 = open('report.xls', 'rb')
    f2 = open('page.docx', 'rb')
    service.post(file_list=[f1, f2])

[0.10.3] - 2024-02-19

  • Fix: Several bugfixes were made to related to literal properties. If a literal is used as a query parameeter, header, path parameter, or request parameter, the user no longer has to explicitly pass it in.

    For example, the following endpoint

    endpoints:
      chat_stream:
        request:
          name: ListUsersRequest
          headers:
            X_API_VERSION: literal<"2022-02-02">
          body:
            properties:
              stream: literal<true>
              query: string

    would generate the following signature in Python

    class Client:
    
      # The user does not have to pass in api version or stream since
      # they are literals and always the same
      def chat_stream(self, *, query: str) -> None:

[0.10.2] - 2024-02-18

  • Fix: The SDK always sends the enum wire value instead of the name of the enum. For example, for the following enum,

    class Operand(str, enum.Enum):
      GREATER_THAN = ">"
      EQUAL_TO = "="

    the SDK should always be sending > and = when making a request.

    This affected enums used in path parameters, query parameters and any request body parameters at the first level. To fix, the SDK sends the .value attribute of the enum.

  • Fix: Revert #2719 which introduced additional issues with circular references within our Python types.

[0.10.1] - 2024-02-14

  • Improvement: Add support for a RequestOptions object for each generated function within Python SDKs. This parameter is an optional final parameter that allows for configuring timeout, as well as pass in arbitrary data through to the request. RequestOptions is a TypedDict, with optional fields, so there's no need to instantiate an object, just pass in the relevant keys within a dict!

    • timeout_in_seconds overrides the timeout for this specific request

    • additional_body_parameters are expanded into the JSON request body

    • additional_query_parameters are expanded into the JSON query parameters map

    • additional_headers are expanded into the request's header map

    • Here's an example:

      client\
        .imdb\
        .create_movie(
          request=CreateMovieRequest(title="title", rating=4.3),
          request_options={
            "timeout_in_seconds": 99,
            "additional_body_parameters": {"another": "body parameter"},
            "additional_headers": {"another": "header"},
          }
        )

[0.10.0] - 2024-02-13

  • Improvement: Remove support for Python 3.7. In order to support newer versions of libraries we depend on (such as typing and typing-extensions), we must move on to Python 3.8. With this change we are also able to:
    • Remove the backports dependency, as cached_property is now included within functools
    • Remove the upper bound dependency on Pydantic which had dropped support for Python 3.7

[0.9.1] - 2024-02-11

  • Fix: Remove literals from SDK function signatures, as they are not modifiable for end users.

    Before:

    def get_options(self, *, dry_run: typing_extensions.Literal[True]) -> Options:
      ...
      json=jsonable_encoder({"dryRun": dry_run}),
      ...

    After:

    def get_options(self, *) -> Options:
      ...
      json=jsonable_encoder({"dryRun": "true"}),
  • Fix: Acknowledge the optionality of a File property, previously we were requiring all File type inputs, even if they were specified as optional within the OpenAPI or Fern definition. Now, we check if the parameter is required and make the parameter optional if it is not.

[0.9.0] - 2024-02-11

  • Feature: The SDK generator now supports whitelabelling. When this is turned on, there will be no mention of Fern in the generated code.

    Note: You must be on the enterprise tier to enable this mode.

[0.8.3-rc0] - 2024-01-29

  • Fix: Increase recursion depth to allow for highly nested and complex examples, this is a temporary solution while the example datamodel is further refined.

[0.8.2-rc0] - 2024-01-28

  • Fix: The Python SDK better handles cyclical references. In particular, cyclical references are tracked for undiscriminated unions, and update_forward_refs is always called with object references.

[0.8.1] - 2024-01-26

  • Feature: If the auth scheme has environment variables specified, the generated python client will scan those environment variables.

    For example, for the following Fern Definition

    auth: APIKey
    auth-schemes:
      APIKey:
        header: X-FERN-API-KEY
        type: string
        env: FERN_API_KEY
    

    the generated client will look like

    import os
    
    class Client:
    
      def __init__(self, *, apiKey: str = os.getenv("FERN_API_KEY"))

[0.8.0] - 2024-01-25

  • Fix: Enums in inlined requests send the appropriate value.

    class Operand(str, Enum):
      greater_than = ">"
      equal_to = "="
    
    # Previously the SDK would just send the operand directly
    def endpoint(self, *, operand: Operand):
      httpx.post(json={"operand": operand})
    
    # Now, the SDK will send the value of the enum
    def endpoint(self, *, operand: Operand):
      httpx.post(json={"operand": operand.value})

[0.7.7] - 2024-01-21

  • Chore: Initialize this changelog