Contributors¶
There are many ways to directly contribute to the project. You can enhance the documentation and user guides, or add additional API models and methods. For both there are guidelines for how to proceed.
Pull Requests¶
Unless you are a project maintainer all pull requests should be made against the main
branch of the project from a fork in your personal GitHub account. It is recommended you work in a feature branch of your fork and periodically pull in changes from main
.
All pull requests must pass all tests and linting as defined in the main_pr_tests.yaml GitHub Actions workflow. Your branch must be up to date with the main
branch. Be sure to pull in all change and resolve merge conflicts before you open your PR.
Documentation¶
The Jamf Pro SDK for Python’s documentation is written in reStructuredText and is built using Sphinx.
Documentation is a combination of hand written user guides and code references rendering the docstrings. If you are contributing updates to existing user guides, or expanding with new content, try to include easy to follow instructions and explanations interspersed with code-block
examples and/or references to SDK objects. As much as possible keep your contributions consistent with existing content.
Important
If you have recommendations for major changes to the documentation - whether rewriting sections or reorganizing content - please open a Feedback issue first for discussion.
Code Contributions¶
Before writing code and opening a pull request to add to the project, please open a Feedback issue for discussion of the proposed changes and ensuring duplicate work is not in flight.
Code contributors are required to uphold project standards:
Consistency with existing SDK interfaces.
All code conforms to formatting and styling (
ruff
is used in this project and is enforced at pull request).All changes are documented in the users guides, references, and docstrings.
Code changes are covered by additional tests (future: this project will not have a full test suite until it comes out of alpha).
Backwards compatibility is not broken by the contributions (with the exception of the alpha period where breaking changes may be allowed on a case-by-case basis).
Your pull request may not be accepted if it does not fulfill all of the requirements listed above.
Dev Environment Setup¶
It is recommended you use a Python virtual environment for local development (see venv.
Tip
The Makefile
included in the project includes shortcut commands that will be referenced in this document. You must install Xcode Command Line Tools
on macOS to use the make
command.
With your virtual environment active run the following from the SDK repository’s directory:
(.venv) % make install
This will install the package in editable mode with all dev and optional dependencies.
There are two additional make
commands for maintaining your local environment.
uninstall
will remove ALL Python packages from your virtual environment allowing you to reinstall cleanly if needed.clean
will remove any directory that’s generated by linting, testing, and building the package. This is useful in the event cached files are causing an issue with running commands.
Code Quality¶
The ruff
tool will enforce formatting standards for the codebase. The settings are defined in pyproject.toml.
make lint
will check if your code is compliant with the formatting and linting rules without making changes.make format
will edit your code to comply with the formatting and linting rules.
Project code is required to use type hinting from the typing
module for all arguments and returns. These should be documented in the docstring following Sphinx’s signatures syntax.
The top of a docstring should include a brief description plus a longer explanation of any special behavior. Any reStructureText can be used in docstrings to better format and emphasize content.
from typing import Iterable
from jamf_pro_sdk.models.classic.computers import ClassicComputersItem
def list_all_computers(self, subsets: Iterable[str] = None) -> List[ClassicComputersItem]:
"""Returns a list of all computers.
:param subsets: (optional) This operations accepts the ``basic`` subset to return
additional details for every computer record. No other subset values are
supported.
:type subsets: Iterable
:return: List of computers.
:rtype: List[ClassicComputersItem]
"""
API Additions¶
Any Jamf Pro API added to the clients must have the following elements code complete before you open a pull request:
The API method has been added to the appropriate client, has a complete docstring, and has an interface in-line with other methods of that client.
The API must have matching and complete Pydantic models.
Provide
@overload
interfaces for API methods with dynamic return types (e.g.Union[list[Computer], Iterator[Page]]
) which be determined from the value of an argument.If the value of a variable, method argument, or return parameter can be
None
, inform the type checker by wrapping its type withOptional[]
, e.g.description: Optional[str] = None
Unless your code is covered by another automated test you will need to add tests to ensure coverage.
The SDK references in the documentation automatically include all public method on the clients and no documentation changes may be required as a part of the contribution.
Pro API Pydantic models can be created by referencing the resources from the OpenAPI schema available on the Jamf Pro server.
All Pro API Pydantic models must subclass from
BaseModel
. This version of Pydantic’sBaseModel
will render correctly in the documentation.
Classic API Pydantic models are more complex as they convert to XML for write operations, and JSON responses from Jamf Pro are known to deviate from the XML representation. If you need to create a Pydantic model for a Classic API resource use the following guidance:
All Classic API Pydantic models must start with
Classic
in the name to prevent conflicts with Pro API models.Use an API response from a running Jamf Pro instance as your reference.
Base your model on the JSON response. Be sure to note and deviations from the XML representation and include those in the doctrings.
- The top-level Pydantic model should subclass from
ClassicApiModel
. Override the
_xml_root_name
. This value should be the top-level key name in the XML (e.g.computer
).Override the
_xml_array_item_names
if applicable. This is a dictionary of attribute name to the XML array item key name (e.g. theextension_attributes
array hasextension_attribute
items). This mapping is used during XML generation for write operations.Override
_xml_write_fields
. This is a Python set of strings that represent the writeable attributes for the object. By default, only these attributes are included when XML is generated from a model.
- The top-level Pydantic model should subclass from
All other nested Classic API Pydantic models must subclass from
BaseModel
. This version of Pydantic’sBaseModel
will render correctly in the documentation.
All API models must be added in the model documentation pages. Model docs are separated by type or API grouping (e.g. Computers, Mobile Devices, etc.). List the top-level model first, and then the nested models for that type in order after.
Here is an example from the Classic API Models page. Follow this pattern for all new model sections.
Computer Groups
---------------
.. currentmodule:: jamf_pro_sdk.models.classic.computer_groups
.. autosummary::
:toctree: _autosummary
:nosignatures:
ClassicComputerGroup
ClassicComputerGroupMember
ClassicComputerGroupMembershipUpdate