Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/2.0 dev #109

Draft
wants to merge 112 commits into
base: master
Choose a base branch
from
Draft

Release/2.0 dev #109

wants to merge 112 commits into from

Conversation

robberwick
Copy link
Collaborator

This PR introduces several key changes aimed at modernizing and improving the BlinkStick Python library:

  • Refactoring: Significant restructuring of the codebase to enhance readability and maintainability. Legacy patterns have been replaced with more efficient and modern Python constructs.

  • Type Hinting: The inclusion of type annotations provides better integration with IDEs and static analysis tools, improving developer experience and reducing runtime errors.

  • Unit Tests: Unit tests have been added to improve the code's reliability and ensure coverage for new and existing features.

  • Project Configuration: The build system now conforms to PEP 517/518 standards by adopting pyproject.toml, replacing older methods for defining project dependencies and metadata.

  • GitHub Actions Integration: Continuous Integration (CI) workflows have been implemented using GitHub Actions to automate testing, linting, and builds, ensuring consistent code quality and streamlined development.

These updates collectively enhance the library's usability, adherence to modern Python standards, and developer experience.

Refactoring

The refactoring changes introduced in the release/2.0-dev branch of the BlinkStick Python library represent a significant overhaul of the codebase. These changes aim to enhance code quality, performance, and maintainability. Key refactoring updates include:

  1. Code Structure and Readability
    Improved organization of classes and functions into smaller, logical units that align with the single-responsibility principle.
    Simplification of complex or redundant logic, making the code easier to understand and debug.
    Removal of legacy constructs and obsolete code, replacing them with Pythonic idioms.
  2. Adoption of Modern Python Features
    Utilization of f-strings for more readable and efficient string formatting.
    Introduction of list comprehensions and generator expressions in place of verbose loops for concise and efficient data processing.
    Use of context managers (e.g., with statements) to handle resources like files or devices, ensuring proper cleanup.
  3. Enhanced Error Handling
    Refined exception handling mechanisms to provide more informative error messages and avoid silent failures.
    Centralization of error management logic for consistent behavior across the library.
  4. Encapsulation and Abstraction
    Refactoring of private and internal methods to ensure proper encapsulation and reduce interdependencies.
    Consolidation of reusable logic into helper functions or utility modules.
  5. Improved Maintainability
    Consistent application of PEP 8 standards across the codebase.
    Addition of docstrings and inline comments to enhance code documentation and ease onboarding for new contributors.

Backend Implementations:

  • Added UnixLikeBackend class in src/blinkstick/backends/unix_like.py to handle BlinkStick devices on Unix-like systems.
  • Added Win32Backend class in src/blinkstick/backends/win32.py to handle BlinkStick devices on Windows systems.

Type Hinting

type hinting has been introduced as a key modernization effort. This update enhances code clarity, facilitates developer productivity, and supports better integration with modern development tools.

Benefits and Implementation of Type Hinting

  • Improved Code Readability:

    Function signatures now explicitly indicate the expected types for parameters and return values. For example:

    def set_color(self, index: int, color: str) -> bool:

    This makes the codebase self-documenting, reducing the need for extensive comments or external documentation.

  • Enhanced Development Tools Support:

    Type hinting integrates seamlessly with IDEs like PyCharm and VS Code, enabling features such as auto-completion, inline documentation, and static type analysis.
    Tools like mypy can now be used to perform static type checks, identifying potential bugs before runtime.

  • Error Reduction:

    Explicit type definitions help prevent errors caused by incorrect data types being passed to functions, improving overall robustness.

  • Compatibility with Modern Python:

    By using Python’s typing module, the library aligns with best practices in modern Python development. This includes the use of advanced typing constructs such as Optional, Union, and List.

  • Foundation for Future Enhancements:

    The consistent use of type hints makes the library easier to extend and maintain, especially for new contributors or developers less familiar with the project.

Examples of Type Hinting Introduced

  • Basic Type Annotations:

    def blink(self, duration: float) -> None:
  • Complex Types:

    def get_device_info(self) -> Optional[Dict[str, Any]]:

Broader Impact

Type hinting not only brings immediate benefits to the BlinkStick project but also positions it as a modern and developer-friendly library in the Python ecosystem. It reduces friction for both current maintainers and new contributors.

Unit Tests

  • Unit tests added, targeting critical parts of the library, including device initialization, data transmission, and mode settings.
  • Tests cover edge cases, ensuring robust error handling and correct functionality under unexpected conditions.

Project Configuration:

  • Updated pyproject.toml to include build system requirements, project metadata, dependencies, optional dependencies, and tool configurations for Black and isort.
  • Removed setup.py and replaced it with pyproject.toml for project configuration and dependency management.
  • Removed MANIFEST and MANIFEST.in files as they are no longer needed with the new project configuration. [1] [2]

GitHub Actions Integration:

  • Added a black.yml workflow to check code formatting using Black on push and pull request events.
  • Added a mypy.yml workflow to perform type checking using Mypy on push and pull request events.
  • Added a pytest.yml workflow to run tests on multiple operating systems and Python versions for pull requests targeting specific branches.

Misc Updates:

  • Updated src/blinkstick/__init__.py to use importlib.metadata for package version retrieval and restructured imports.
  • Added a new example script examples/random_color.py to demonstrate BlinkStick usage and exception handling.

These changes introduce platform-specific backend implementations for better device handling, improve project configuration management, and enhance the project's CI/CD pipeline, , and .

Abstract away the platform specifics in the main BlinkStick class by employing a strategy pattern.
Add a minimal instantiation test for all 3 blinkstick classes.
Add pytest as test dependency and stub out GitHub action for cross-platform testing on supported python versions
test: rename blinkstick test file
Return BlinkStickVariant from get_variant

BREAKING CHANGE: get_variant() now returns an instance of the BlinkStickVariant Enum, where the value is a 2-tuple of variant value, and variant string
Update the test for the get_variant and get_variant_string methods to account for the new BlinkStickVariant enum
Use Enum to capture BlinkStick variant types
Add tests for string to bytes conversion and refactor
Rename `find_blinksticks` to `get_attached_blinkstick_devices`, and `_refresh_device` to `_refresh_attached_blinkstick_device`
Always return a list from the usb backend, so if no blinkstick devices are detected, the list should be empty
Use the BlinkStickDevice class to retrieve readonly device data up front, and persist it in the BlinkStick wrapper class
Use the BlinkStickDevice class to retrieve readonly device data up front, and persist it in the BlinkStick wrapper class
Rationalise accessing of read-only device attributes by use of a BlinkStickDevice class
Remove Unused find blinksticks method
move the main client classes (BlinkStick, BlinkStickPro, BlinkStickProMatrix) to a clients package

Also, move the core functions (find_first etc) to core module
organise client and core code
move the entrypoint script into a scripts folder to keep things tidy.
add a py.typed file to the package to indicate to mypy that it uses type hinting
Rename BlinkStickVariant.identify() to .from_version_attrs(), for added clarity.
Add a serial number model so that it's easier to decompose th estring into constituent parts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant