stubber.publish.stubpackage =========================== .. py:module:: stubber.publish.stubpackage .. autoapi-nested-parse:: Create a stub-only package for a specific - version - port - board of micropython Attributes ---------- .. autoapisummary:: stubber.publish.stubpackage.Status stubber.publish.stubpackage.StubSources Classes ------- .. autoapisummary:: stubber.publish.stubpackage.VersionedPackage stubber.publish.stubpackage.Builder stubber.publish.stubpackage.PoetryBuilder stubber.publish.stubpackage.StubPackage Functions --------- .. autoapisummary:: stubber.publish.stubpackage.get_top_level_names stubber.publish.stubpackage.append_new_definitions Module Contents --------------- .. py:data:: Status .. py:data:: StubSources .. py:function:: get_top_level_names(source: str) -> Set[str] Get names of top-level class/function/variable definitions from Python or stub source. Uses libcst so that comments, decorators and whitespace are preserved for callers that need to round-trip the code. .. py:function:: append_new_definitions(target_path: pathlib.Path, complement_path: pathlib.Path) -> bool Append definitions from *complement_path* that do not yet exist in *target_path*. This is used for complementary frozen modules that extend a C-module. Only new top-level class/function/variable definitions are added; existing definitions in the target are never modified or duplicated. Uses libcst for parsing so that all formatting, comments and decorators are fully preserved when extracting code fragments. Returns ``True`` if any definitions were appended, ``False`` otherwise. .. py:class:: VersionedPackage(package_name: str, *, mpy_version: str) Represents a versioned package. .. attribute:: package_name The name of the package. :type: str .. attribute:: mpy_version The MicroPython version. :type: str .. method:: __init__(self, package_name str, mpy_version: str): Initializes a new instance of the VersionedPackage class. .. method:: is_preview(self) Checks if the package is a preview version. .. method:: pkg_version(self) -> str Returns the version of the package. .. method:: pkg_version(self, version str) -> None: Sets the version of the package. .. method:: get_prerelease_package_version(self, production bool = False) -> str: Gets the next prerelease version for the package. .. method:: get_next_package_version(self, prod bool = False, rc=False) -> str: Gets the next version for the package. .. method:: next_pkg_version(self, production bool) -> str: Gets the next version for the package. .. method:: bump(self, *, rc int = 0) -> str: Bumps the postrelease version of the package. .. py:attribute:: package_name :type: str .. py:attribute:: mpy_version :type: str .. py:attribute:: _pkg_version :type: str .. py:method:: __str__() -> str .. py:method:: __repr__() -> str .. py:method:: __eq__(o: object) -> bool .. py:method:: __hash__() -> int .. py:property:: pkg_version :type: str return the version of the package .. py:method:: next_package_version(production: bool) -> str Get the next version for the package .. py:method:: is_preview() .. py:method:: _get_next_preview_package_version(production: bool = False) -> str Get the next prerelease version for the package. this is used for preview versions of micropython (-preview, formerly known as 'latest') .. py:method:: _get_next_package_version(prod: bool = False, rc=False) -> str Get the next version for the package. .. py:method:: bump(*, rc: int = 0) -> str bump the postrelease version of the package, and write the change to disk if rc >= 1, the version is bumped to the specified release candidate .. py:class:: Builder(package_name: str, *, mpy_version: str = '0.0.1', port: str, board: str = GENERIC_U, variant: Optional[str] = None, description: str = 'MicroPython stubs', stub_sources: Optional[StubSources] = None) Bases: :py:obj:`VersionedPackage` Builder class for creating and updating MicroPython stub packages. :param package_name: The name of the package. :type package_name: str :param mpy_version: The version of MicroPython. Defaults to "0.0.1". :type mpy_version: str, optional :param port: The port for the package. :type port: str :param board: The board for the package. Defaults to GENERIC_U. :type board: str, optional :param description: The description of the package. Defaults to "MicroPython stubs". :type description: str, optional :param stubs: The stub sources for the package. Defaults to None. :type stubs: Optional[StubSources], optional .. attribute:: package_name The name of the package. :type: str .. attribute:: mpy_version The version of MicroPython. :type: str .. attribute:: port The port for the package. :type: str .. attribute:: board The board for the package. :type: str .. attribute:: description The description of the package. :type: str .. attribute:: stub_sources The stub sources for the package. :type: Optional[StubSources] .. attribute:: hash The hash of all the files in the package. :type: None .. attribute:: stub_hash The hash of the stub files. :type: None Properties: package_path (Path): The package path based on the package name and version, relative to the publish folder. toml_path (Path): The path to the `pyproject.toml` file. pyproject (Union[Dict[str, Any], None]): The parsed pyproject.toml or None. .. method:: create_update_pyproject_toml() Create or update/overwrite a `pyproject.toml` file. .. method:: check() Check if the package is valid. .. method:: clean() Remove the stub files from the package folder. .. method:: copy_stubs() Copy files from all listed stub folders to the package folder. .. method:: update_package_files() Update the stub-only package for a specific version of MicroPython. .. method:: write_package_json() Write the package.json file to disk. .. method:: to_dict() Return the package as a dict to store in the jsondb. .. method:: from_dict(json_data Dict): Load the package from a dict (from the jsondb). .. method:: calculate_hash(include_md bool = True): Create a SHA1 hash of all files in the package. .. method:: update_hashes() Update the package hashes. .. method:: is_changed(include_md bool = True): Check if the package has changed. .. py:attribute:: BUF_SIZE :value: 1048576 .. py:attribute:: _publish :value: True .. py:attribute:: package_name .. py:attribute:: mpy_version :value: '0.0.1' .. py:attribute:: port .. py:attribute:: board :value: 'GENERIC' .. py:attribute:: variant :value: '' .. py:attribute:: description :value: 'MicroPython stubs' .. py:attribute:: stub_sources :value: [] .. py:attribute:: hash :value: None Hash of all the files in the package .. py:attribute:: stub_hash :value: None Hash of all .pyi files .. py:property:: package_path :type: pathlib.Path package path based on the package name and version and relative to the publish folder .. py:property:: toml_path :type: pathlib.Path the path to the `pyproject.toml` file .. py:property:: pyproject :type: Union[Dict[str, Any], None] parsed pyproject.toml or None .. py:method:: create_update_pyproject_toml() -> None :abstractmethod: create or update/overwrite a `pyproject.toml` file by combining a template file with the given parameters. .. py:method:: check() -> bool Check if the package is valid, to be implemented by the subclass .. py:method:: clean() -> None Remove the stub files from the package folder This is used before update the stub package, to avoid lingering stub files, and after the package has been built, to avoid needing to store files multiple times. `.gitignore` cannot be used as this will prevent poetry from processing the files. .. py:method:: copy_stubs() -> None Copy files from all listed stub folders to the package folder the order of the stub folders is relevant as "last copy wins" - 1 - Copy all firmware stubs (or merged) to the package folder - 2 - copy the remaining stubs to the package folder - 3 - remove *.py files from the package folder .. py:method:: update_umodules() Replace the STDLIB umodules with a simple import statement in order to allow the typecheckers to resovle the stdlib modules in the usual stdlib location. .. py:method:: copy_folder(stub_type: stubber.publish.enums.StubSource, src_path: pathlib.Path) .. py:method:: update_package_files() -> None Update the stub-only package for a specific version of micropython - cleans the package folder - copies the stubs from the list of stubs. - creates/updates the readme and the license file .. py:method:: write_package_json() -> None write the package.json file to disk .. py:method:: to_dict() -> dict return the package as a Dict[str,str] to store in the db need to simplify some of the Objects to allow serialization to json - stub_sources List[Tuple[StubSource, Path]] -> List[List[str, str]] # convert the paths to posix paths - the version (semver) to a string - toml file to list of lines .. py:method:: from_dict(json_data: Dict) -> None load the package from a dict (from the db) .. py:method:: calculate_hash(include_md: bool = True) -> str Create a SHA1 hash of all files in the package, excluding the pyproject.toml file itself. the hash is based on the content of the .py/.pyi and .md files in the package. if include_md is False , the .md files are not hased, allowing the files in the packeges to be compared simply As a single hash is created across all files, the files are sorted prior to hashing to ensure that the hash is stable. Note: A changed hash will not indicate which of the files in the package have been changed. .. py:method:: add_file_hash(file, file_hash) Adds the hash of a file to the given file hash object. If an error occurs, the file is retried up to 3 times with a 0.2 second delay :param file: The path to the file. :type file: str :param file_hash: The file hash object to update. :type file_hash: hashlib._Hash :returns: None .. py:method:: update_hashes(ret=False) -> None Update the package hashes. Resets is_changed() to False .. py:method:: is_changed(include_md: bool = True) -> bool Check if the package has changed, based on the current and the stored hash. The default checks the hash of all files, including the .md files. .. py:method:: create_license() -> None Create a license file for the package - copied from the template license file .. py:method:: create_readme() -> None Create a readme file for the package - based on the template readme file - with a list of all included stub folders added to it (not the individual stub-files) .. py:class:: PoetryBuilder(package_name: str, *, port: str, mpy_version: str = '0.0.1', board: str = GENERIC_U, description: str = 'MicroPython stubs', stub_sources: Optional[StubSources] = None, json_data: Optional[Dict[str, Any]] = None) Bases: :py:obj:`Builder` Build a package using Poetry .. py:property:: pkg_version :type: str return the version of the package .. py:method:: poetry_build() -> bool build the package by running `poetry build` .. py:method:: poetry_publish(production: bool = False) -> bool .. py:method:: run_poetry(parameters: List[str]) -> bool Run a poetry commandline in the package folder. Note: this may write some output to the console ('All set!') .. py:method:: check() -> bool check if the package is valid by running `poetry check` Note: this will write some output to the console ('All set!') .. py:method:: create_update_pyproject_toml() -> None create or update/overwrite a `pyproject.toml` file by combining a template file with the given parameters. and updating it with the pyi files included .. py:method:: update_pyproject_stubs() -> int Add the stub files to the pyproject.toml file .. py:class:: StubPackage(package_name: str, port: str, *, board: str = GENERIC_U, version: str = '0.0.1', description: str = 'MicroPython stubs', stub_sources: Optional[StubSources] = None, json_data: Optional[Dict[str, Any]] = None) Bases: :py:obj:`PoetryBuilder` Create a stub-only package for a specific version , port and board of micropython properties: - toml_path - the path to the `pyproject.toml` file - package_path - the path to the folder where the package info will be stored ('./publish'). - pkg_version - the version of the package as used on PyPi (semver). Is stored directly in the `pyproject.toml` file - pyproject - the contents of the `pyproject.toml` file .. method:: - from_json - load the package from json .. method:: - to_json - return the package as json .. method:: - create_update_pyproject_toml - create or update the `pyproject.toml` file .. method:: - create_readme - create the readme file .. method:: - create_license - create the license file .. method:: - copy_stubs - copy the stubs to the package folder .. method:: - update_included_stubs - update the included stubs in the `pyproject.toml` file .. method:: - create_hash - create a hash of the package files .. method:: - update_package_files - combines clean, copy, and create reeadme & updates .. py:attribute:: port .. py:attribute:: board :value: 'GENERIC' .. py:attribute:: status :type: Status .. py:method:: _handle_firmware_source(fw_path: pathlib.Path) -> pathlib.Path Handle FIRMWARE source: prefer -merged stubs over bare firmware stubs. .. py:method:: _handle_frozen_source(fw_path: pathlib.Path) -> Optional[pathlib.Path] Handle FROZEN source: fallback to GENERIC folder if board specific doesn't exist. .. py:method:: _handle_merged_source(fw_path: pathlib.Path) -> pathlib.Path Handle MERGED source: use default board folder instead of GENERIC if available. .. py:method:: _handle_default_source(fw_path: pathlib.Path) -> pathlib.Path Handle default source types: return path as-is. .. py:method:: update_sources() -> StubSources Update the stub sources with optimized paths: - FIRMWARE: prefer -merged stubs over bare firmware stubs - FROZEN: fallback to GENERIC folder if board specific folder doesn't exist - MERGED: use default board folder instead of GENERIC if available .. py:method:: update_distribution(production: bool) -> bool Update the package .pyi files, if all the sources are available .. py:method:: build_distribution(production: bool, force=False) -> bool Build a package look up the previous package version in the dabase - update package files - build the wheels and sdist :param production: PyPI or Test-PyPi - :param force: BUILD even if no changes :return: True if the package was built .. py:method:: publish_distribution_ifchanged(db_conn: sqlite3.Connection, *, production: bool, build=False, force=False, dry_run=False, clean: bool = False) -> bool Publish a package to PyPi look up the previous package version in the dabase, and only publish if there are changes to the package - change determied by hash across all files Build - update package files - build the wheels and sdist Publish - publish to PyPi - update database with new hash .. py:method:: publish_distribution(dry_run: bool, production: bool, db_conn: sqlite3.Connection) -> bool Publishes the package to PyPi or Test-PyPi. :param dry_run: If True, performs a dry run without actually publishing. :type dry_run: bool :param production: If True, publishes to PyPi. If False, publishes to Test-PyPi. :type production: bool :param db: The database object to save the package state. :returns: True if the publish was successful, False otherwise. :rtype: bool .. py:method:: are_package_sources_available() -> bool Check if (all) the packages sources exist.