diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 1a268ea3..49a5c1a3 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -1,11 +1,16 @@ -name: Publish SDK to Test PyPI -on: [workflow_dispatch] +name: Publish pre-release to Test PyPI +on: + push: + branches: + - develop + - release/2.x + workflow_dispatch: env: PYTHON_VERSION: 3.13 jobs: - publish-to-test-pypi: + publish-pre-release: runs-on: ubuntu-latest permissions: id-token: write @@ -17,6 +22,13 @@ jobs: with: python-version: ${{ env.PYTHON_VERSION }} deps-group: release + - name: Set pre-release version + env: + RUN_NUMBER: ${{ github.run_number }} + run: | + SHA=$(git rev-parse --short HEAD) + BASE=$(uv version --short) + uv version --frozen "${BASE}.dev${RUN_NUMBER}+g${SHA}" - name: Build packages for distribution run: uv build - name: Publish packages to Test PyPI diff --git a/docs/conf.py b/docs/conf.py index 20d094dd..48e2cee4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -9,10 +9,9 @@ # All configuration values have a default; values that are commented out # serve to show the default. +import importlib.metadata from datetime import datetime -import splunklib - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. @@ -40,17 +39,17 @@ master_doc = "index" # General information about the project. -project = "Splunk SDK for Python" -copyright = f"{datetime.now().year}, Splunk Inc." +package_name = "splunk-sdk" +project = f"Splunk SDK for Python (f{package_name}/splunklib)" +copyright = f"2011-{datetime.now().year} Splunk, Inc." # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = splunklib.__version__ -# The full version, including alpha/beta/rc tags. -release = splunklib.__version__ +release = importlib.metadata.version(package_name) +version = ".".join(release.split(".")[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pyproject.toml b/pyproject.toml index 708f0d14..aef9cdd7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ download = "https://github.com/splunk/splunk-sdk-python/releases/latest" [project] name = "splunk-sdk" -dynamic = ["version"] +version = "3.0.0" description = "Splunk Software Development Kit for Python" readme = "README.md" requires-python = ">=3.13" @@ -57,8 +57,7 @@ dev = [ ] [build-system] -# setuptools v61 introduces pyproject.toml support -requires = ["setuptools>=61.0.0"] +requires = ["setuptools>=82.0.1"] build-backend = "setuptools.build_meta" [tool.setuptools] @@ -71,9 +70,6 @@ packages = [ "splunklib.ai.engines", ] -[tool.setuptools.dynamic] -version = { attr = "splunklib.__version__" } - [tool.basedpyright] exclude = [".venv"] allowedUntypedLibraries = ["splunklib"] diff --git a/splunklib/__init__.py b/splunklib/__init__.py index a6639738..fc83e84a 100644 --- a/splunklib/__init__.py +++ b/splunklib/__init__.py @@ -30,7 +30,3 @@ def setup_logging( level, log_format=DEFAULT_LOG_FORMAT, date_format=DEFAULT_DATE_FORMAT ): logging.basicConfig(level=level, format=log_format, datefmt=date_format) - - -__version_info__ = (3, 0, 0) -__version__ = ".".join(map(str, __version_info__)) diff --git a/splunklib/binding.py b/splunklib/binding.py index 1684a50e..39ea2b2a 100644 --- a/splunklib/binding.py +++ b/splunklib/binding.py @@ -24,6 +24,7 @@ :mod:`splunklib.client` module. """ +import importlib.metadata import io import json import logging @@ -34,14 +35,13 @@ from contextlib import contextmanager from datetime import datetime from functools import wraps -from io import BytesIO -from urllib import parse from http import client from http.cookies import SimpleCookie +from io import BytesIO +from urllib import parse from xml.etree.ElementTree import XML, ParseError -from .data import record -from . import __version__ +from .data import record logger = logging.getLogger(__name__) @@ -1787,9 +1787,11 @@ def connect(scheme, host, port): def request(url, message, **kwargs): scheme, host, port, path = _spliturl(url) body = message.get("body", "") + + sdk_version = importlib.metadata.version("splunk-sdk") head = { "Content-Length": str(len(body)), - "User-Agent": "splunk-sdk-python/%s" % __version__, + "User-Agent": f"splunk-sdk-python/{sdk_version}", "Accept": "*/*", "Connection": "Close", } # defaults diff --git a/splunklib/client.py b/splunklib/client.py index 8e745442..9b7a07f4 100644 --- a/splunklib/client.py +++ b/splunklib/client.py @@ -32,10 +32,10 @@ jobs, saved searches, inputs, and indexes). All of these fields are :class:`Collection` objects:: - appcollection = service.apps - my_app = appcollection.create('my_app') - my_app = appcollection['my_app'] - appcollection.delete('my_app') + app_collection = service.apps + my_app = app_collection.create('my_app') + my_app = app_collection['my_app'] + app_collection.delete('my_app') The individual elements of the collection, in this case *applications*, are subclasses of :class:`Entity`. An ``Entity`` object has fields for its @@ -887,7 +887,7 @@ def get(self, path_segment="", owner=None, app=None, sharing=None, **query): ('content-type', 'text/xml; charset=utf-8')], 'reason': 'OK', 'status': 200} - apps.get('nonexistant/path') # raises HTTPError + apps.get('nonexistent/path') # raises HTTPError s.logout() apps.get() # raises AuthenticationError """ @@ -969,7 +969,7 @@ def post(self, path_segment="", owner=None, app=None, sharing=None, **query): ('content-type', 'text/xml; charset=utf-8')], 'reason': 'Created', 'status': 201} - apps.get('nonexistant/path') # raises HTTPError + apps.get('nonexistent/path') # raises HTTPError s.logout() apps.get() # raises AuthenticationError """ @@ -1468,7 +1468,7 @@ def __iter__(self, **kwargs): :type kwargs: ``dict`` :rtype: iterator over entities. - Implemented to give Collection a listish interface. This + Implemented to give Collection a list-ish interface. This function always makes a roundtrip to the server, plus at most two additional round trips if the ``autologin`` field of :func:`connect` is set to ``True``. @@ -1488,7 +1488,7 @@ def __iter__(self, **kwargs): def __len__(self): """Enable ``len(...)`` for ``Collection`` objects. - Implemented for consistency with a listish interface. No + Implemented for consistency with a list-ish interface. No further failure modes beyond those possible for any method on an Endpoint. @@ -1867,7 +1867,7 @@ def get(self, name="", owner=None, app=None, sharing=None, **query): ('content-type', 'text/xml; charset=utf-8')], 'reason': 'OK', 'status': 200} - saved_searches.get('nonexistant/search') # raises HTTPError + saved_searches.get('nonexistent/search') # raises HTTPError s.logout() saved_searches.get() # raises AuthenticationError @@ -1967,7 +1967,7 @@ def delete(self, key): def _entity_path(self, state): # Overridden to make all the ConfigurationFile objects # returned refer to the configs/ path instead of the - # properties/ path used by Configrations. + # properties/ path used by Configurations. return PATH_CONF % state["title"] @@ -3204,7 +3204,7 @@ def create(self, query, **kwargs): :param query: The search query. :type query: ``string`` - :param kwargs: Additiona parameters (optional). For a list of available + :param kwargs: Additional parameters (optional). For a list of available parameters, see `Search job parameters `_ on Splunk Developer Portal. diff --git a/uv.lock b/uv.lock index 348d058a..12b2b3cc 100644 --- a/uv.lock +++ b/uv.lock @@ -1646,6 +1646,7 @@ wheels = [ [[package]] name = "splunk-sdk" +version = "3.0.0" source = { editable = "." } [package.optional-dependencies]