uuid_extension-0.2.0/0000775000175000017500000000000015115522155014055 5ustar edwardedwarduuid_extension-0.2.0/.python-version0000644000175000017500000000000413615410400017042 0ustar edwardedward3.8 uuid_extension-0.2.0/README.md0000644000175000017500000000402713615410400015325 0ustar edwardedward# UUID Extension for Python A Python library implementing UUID version 7 as specified in the RFC, providing time-ordered UUIDs for modern applications. ## Features - Full implementation of UUID version 7 - Time-ordered UUIDs for better database performance - Compatible with standard Python UUID objects - Timestamp extraction capabilities - Optional counter for monotonicity within milliseconds ## Installation ```bash pip install uuid-extension ``` ## Usage ### Basic Usage ```python from uuid_extension import uuid7 # Generate a new UUID7 uuid = uuid7() print(uuid) # e.g., 018c1585-5e7c-7601-b322-5bf9f7478708 # Access the underlying UUID object uuid_obj = uuid.uuid7 ``` ### With Timestamp ```python from datetime import datetime from uuid_extension import uuid7 # Generate UUID7 with a specific timestamp custom_time = datetime.now() uuid = uuid7(timestamp=custom_time) # Or with Unix timestamp uuid = uuid7(timestamp=1690000000.123) ``` ### With Counter ```python from uuid_extension import uuid7 # Use a counter for guaranteeing monotonicity within the same millisecond counter = 1 id1 = uuid7(counter=counter) counter += 1 id2 = uuid7(counter=counter) ``` ### Time Extraction ```python from uuid_extension import uuid7 uuid = uuid7() # Extract timestamp as float (Unix timestamp in seconds) ts = uuid.to_timestamp() # Extract as datetime object (UTC timezone by default) dt = uuid.to_datetime() # Extract as datetime with a specific timezone import pytz dt_est = uuid.to_datetime(tz=pytz.timezone('US/Eastern')) ``` ### Comparison Operations UUID7 objects support standard comparison operations: ```python id1 = uuid7() id2 = uuid7() print(id1 == id2) # False print(id1 < id2) # True (usually, as they're time-ordered) print(id1 <= id2) # True ``` ## Technical Details UUID version 7 structure: - 48 bits of Unix timestamp in milliseconds - 4 bits for version (set to 7) - 2 bits for variant (set to 0b10) - 74 bits of random data for uniqueness ## License MIT License uuid_extension-0.2.0/docs/0000775000175000017500000000000015115522155015005 5ustar edwardedwarduuid_extension-0.2.0/docs/bitwise.md0000644000175000017500000002617513615410400016776 0ustar edwardedward# Understanding Bitwise Operations in Python This guide explains bitwise operations with a focus on the expression `(uuid_int >> 80) & 0xFFFFFFFFFFFF`. We'll break down each operation, provide examples with visualization, and explore practical applications. ## Table of Contents 1. [Basic Concepts](#basic-concepts) 2. [Bitwise Operators](#bitwise-operators) 3. [Breaking Down Our Example](#breaking-down-our-example) 4. [Step-by-Step Execution](#step-by-step-execution) 5. [Common Use Cases](#common-use-cases) ## Basic Concepts ### Bits and Binary A bit is the most basic unit of information in computing, representing either 0 or 1. Multiple bits form binary numbers: ``` Decimal: 13 Binary: 00001101 ↑↑↑↑↑↑↑↑ 87654321 (bit positions) ``` ### Hexadecimal Notation Hexadecimal (base 16) uses 0-9 and A-F to represent 16 values: ``` Decimal: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Hexadecimal: 0 1 2 3 4 5 6 7 8 9 A B C D E F ``` Example: `0xFF` = 255 decimal = `11111111` binary ## Bitwise Operators ### Bitwise AND (`&`) Compares each bit position; results in 1 only if both bits are 1. ``` 1101 (13) & 1010 (10) ---- 1000 (8) ``` Example: ```python a = 13 # 1101 in binary b = 10 # 1010 in binary result = a & b print(f"{a} & {b} = {result}") # Output: 13 & 10 = 8 ``` ### Bitwise OR (`|`) Compares each bit position; results in 1 if either bit is 1. ``` 1101 (13) | 1010 (10) ---- 1111 (15) ``` Example: ```python a = 13 # 1101 in binary b = 10 # 1010 in binary result = a | b print(f"{a} | {b} = {result}") # Output: 13 | 10 = 15 ``` ### Bitwise XOR (`^`) Compares each bit position; results in 1 only if exactly one bit is 1. ``` 1101 (13) ^ 1010 (10) ---- 0111 (7) ``` Example: ```python a = 13 # 1101 in binary b = 10 # 1010 in binary result = a ^ b print(f"{a} ^ {b} = {result}") # Output: 13 ^ 10 = 7 ``` ### Bitwise NOT (`~`) Inverts all bits (0 becomes 1, 1 becomes 0). ``` ~ 1101 (13) ---- 0010 (-14 in two's complement) ``` Example: ```python a = 13 # 1101 in binary result = ~a print(f"~{a} = {result}") # Output: ~13 = -14 ``` Note: In Python, NOT operates using two's complement, so ~n = -n-1 ### Bitwise Left Shift (`<<`) Shifts bits to the left by a specified number of positions, filling with 0s on the right. ``` 13 << 2: Before: 00001101 (13) After: 00110100 (52) ``` Example: ```python a = 13 shift = 2 result = a << shift print(f"{a} << {shift} = {result}") # Output: 13 << 2 = 52 ``` ### Bitwise Right Shift (`>>`) Shifts bits to the right by a specified number of positions. ``` 13 >> 2: Before: 00001101 (13) After: 00000011 (3) ``` Example: ```python a = 13 shift = 2 result = a >> shift print(f"{a} >> {shift} = {result}") # Output: 13 >> 2 = 3 ``` ## Breaking Down Our Example Let's analyze: `(uuid_int >> 80) & 0xFFFFFFFFFFFF` This expression: 1. Takes a UUID integer value 2. Shifts it right by 80 bits 3. Performs a bitwise AND with `0xFFFFFFFFFFFF` (a 48-bit mask with all 1s) ## Step-by-Step Execution ### Example with a Sample UUID Let's work with UUID: `123e4567-e89b-12d3-a456-426614174000` As an integer: `0x123e4567e89b12d3a456426614174000` #### Step 1: Understanding the Structure This UUID integer in binary is 128 bits long: ``` UUID Integer: 0001 0010 0011 1110 0100 0101 0110 0111 1110 1000 1001 1011 0001 0010 1101 0011 1010 0100 0101 0110 0100 0010 0110 0110 0001 0100 0001 0111 0100 0000 0000 0000 ``` #### Step 2: Right Shift by 80 `uuid_int >> 80` shifts all bits 80 positions to the right: ``` Before shift (simplified view of most significant bits): 0001 0010 0011 1110 0100 0101 0110 0111 1110 1000 1001 1011 0001 0010 1101 0011... After shift (80 bits from right removed): ...0000 0000 0001 0010 0011 1110 0100 0101 0110 0111 1110 1000 1001 1011 0001 0010 ``` Result: `0x123e4567e89b` #### Step 3: Bitwise AND with Mask The mask `0xFFFFFFFFFFFF` is 48 bits of all 1s: ``` Shifted value: 0000 0000 0001 0010 0011 1110 0100 0101 0110 0111 1110 1000 1001 1011 0001 0010 Mask: 0000 0000 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 Result: 0000 0000 0001 0010 0011 1110 0100 0101 0110 0111 1110 1000 1001 1011 0001 0010 ``` The mask preserves the 48 least significant bits of the shifted value. Final result: `0x123e4567e89b` ### Understanding Bit Shifting in Depth Bit shifting is a fundamental operation that moves bits left or right within a binary representation: #### Right Shift (`>>`) - **Definition**: Moves all bits to the right by the specified number of positions - **Effect**: Divides the number by 2^n (where n is the shift amount) - **Lost Information**: Bits shifted beyond the right edge are discarded - **Padding**: Most significant bits are filled with 0s (logical shift) or the sign bit (arithmetic shift) **Visual Example**: ``` Decimal 173 (10101101 in binary) right-shifted by 3: Before: 10101101 After: 00010101 (equals decimal 21) ↑↑↑ ← New 0s inserted on the left ``` Right shift by 80 bits effectively divides the uuid_int by 2^80, extracting only the higher bit positions. ### Masking Operations Explained Bit masking uses bitwise AND to selectively filter bits: #### Bitwise AND Mask - **Purpose**: Keeps only the bits you want, zeros out the rest - **Creation**: Set 1s in positions to keep, 0s in positions to clear - **Formula**: `result = value & mask` - **Common Masks**: - `0xFF`: Preserve only the lowest 8 bits - `0xFFFFFFFFFFFF`: Preserve 48 bits (as in our example) - `0x01`: Check if the least significant bit is set **Mask Patterns**: ``` Keep lower 4 bits: 0000 1111 (0x0F) Keep upper 4 bits: 1111 0000 (0xF0) Keep specific bits: 0101 0101 (0x55) ``` ### Why Use `0xFFFFFFFFFFFF` in Our Example? The 48-bit mask (`0xFFFFFFFFFFFF`) serves a specific purpose: 1. **Size Limitation**: Ensures the result doesn't exceed 48 bits (6 bytes) 2. **Data Integrity**: Removes any potential higher bits that might exist after the shift 3. **Standardization**: Forces the result into a consistent bit-length format 4. **UUID Structure**: Targets specific segments of the UUID structure This technique combines shifting and masking to precisely extract 48 bits from a specific position in the 128-bit UUID. ### Code Demonstration: ```python # Example with the UUID: 123e4567-e89b-12d3-a456-426614174000 uuid_int = 0x123e4567e89b12d3a456426614174000 print(f"Original UUID integer: {uuid_int}") print(f"Hexadecimal: 0x{uuid_int:032x}") # Step 1: Right shift by 80 shifted = uuid_int >> 80 print(f"\nAfter shifting right by 80 bits: {shifted}") print(f"Hexadecimal: 0x{shifted:x}") # Step 2: Apply the mask with bitwise AND mask = 0xFFFFFFFFFFFF result = shifted & mask print(f"\nMask: 0x{mask:x}") print(f"After applying the mask: {result}") print(f"Hexadecimal: 0x{result:x}") ``` Output: ``` Original UUID integer: 24197857161011715162171839636988778528768 Hexadecimal: 0x123e4567e89b12d3a456426614174000 After shifting right by 80 bits: 81985529216411 Hexadecimal: 0x123e4567e89b Mask: 0xffffffffffff After applying the mask: 81985529216411 Hexadecimal: 0x123e4567e89b ``` ## Common Use Cases 1. **Extracting Fields from UUIDs**: As in our example, isolating specific bit fields - Example: Getting timestamp components from time-based UUIDs - Example: Extracting node identifiers from MAC address-based UUIDs 2. **Mask Operations**: Selectively preserving or clearing bits - Clearing specific flags: `status &= ~FLAG_BITS` - Setting specific flags: `status |= FLAG_BITS` - Toggling specific flags: `status ^= FLAG_BITS` - Checking if flags are set: `if (status & FLAG_BITS) == FLAG_BITS` 3. **Efficient Division/Multiplication**: Using shifts for powers of 2 4. **Flag Manipulation**: Setting, checking, and clearing flags in a single integer 5. **Low-Level Memory Operations**: Direct manipulation of memory contents ## Role-Based Access Control Example Bitwise operations provide an elegant way to implement role-based access control systems. Here's a practical example demonstrating how to define, assign, and check user roles: ### Defining Roles Using Bit Flags Each role is assigned a power of 2 so each bit position represents a distinct role: ```python # Role definitions (each role is a distinct bit) NOT_LOGGED_IN = 0 # 00000000 USER = 1 # 00000001 EDITOR = 2 # 00000010 ADMIN = 4 # 00000100 SUPER_ADMIN = 8 # 00001000 ``` ### Assigning Multiple Roles Combining roles is achieved with the bitwise OR (`|`) operator: ```python # User with multiple roles (both USER and EDITOR permissions) user_roles = USER | EDITOR # 00000011 (decimal 3) # Admin with all permissions admin_roles = USER | EDITOR | ADMIN | SUPER_ADMIN # 00001111 (decimal 15) ``` ### Checking for Roles Testing for specific roles uses the bitwise AND (`&`) operator: ```python def has_role(user_roles, role): """Check if the user has a specific role.""" return (user_roles & role) == role def check_access(user_roles): """Demonstrate role checking.""" if user_roles == NOT_LOGGED_IN: print("Not logged in - access denied") elif has_role(user_roles, ADMIN): print("Admin access granted - full control") elif has_role(user_roles, EDITOR): print("Editor access granted - can edit content") elif has_role(user_roles, USER): print("User access granted - can view content") else: print("Unknown role configuration") # Example usage regular_user = USER # Just a regular user content_editor = USER | EDITOR # User with editor privileges site_admin = USER | EDITOR | ADMIN # User with admin privileges check_access(regular_user) # Output: User access granted - can view content check_access(content_editor) # Output: Editor access granted - can edit content check_access(site_admin) # Output: Admin access granted - full control ``` ### Adding and Removing Roles Dynamically modify permissions without affecting other roles: ```python # Granting a role (using bitwise OR) def grant_role(user_roles, role): return user_roles | role # Revoking a role (using bitwise AND with complement) def revoke_role(user_roles, role): return user_roles & ~role # Example: Promote a regular user to editor user_roles = USER print(f"Initial roles: {user_roles:08b}") # 00000001 user_roles = grant_role(user_roles, EDITOR) print(f"After promotion: {user_roles:08b}") # 00000011 # Example: Revoke editor role user_roles = revoke_role(user_roles, EDITOR) print(f"After demotion: {user_roles:08b}") # 00000001 ``` ### Benefits of Bitwise Role Management 1. **Storage Efficiency**: Represents multiple roles in a single integer 2. **Performance**: Role checking is a simple bitwise operation 3. **Flexibility**: Easily add or remove roles without affecting others 4. **Scalability**: Supports up to 32 or 64 distinct roles (depending on integer size) 5. **Compatibility**: Works well with database storage and API transmission This pattern is commonly used in: - Operating system permission systems (read, write, execute) - Web application authorization frameworks - Database access control mechanisms - Game development (character attributes, status effects)uuid_extension-0.2.0/docs/specs.md0000644000175000017500000000000013615410400016420 0ustar edwardedwarduuid_extension-0.2.0/.gitignore0000644000175000017500000000661713615410400016045 0ustar edwardedward# own .DS_Store dev dev.py # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder .pybuilder/ target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv # For a library or package, you might want to ignore these files since the code is # intended to run in multiple environments; otherwise, check them in: # .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # UV # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. #uv.lock # poetry # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. # This is especially recommended for binary packages to ensure reproducibility, and is more # commonly ignored for libraries. # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control #poetry.lock # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it # in version control. # https://pdm.fming.dev/latest/usage/project/#working-with-version-control .pdm.toml .pdm-python .pdm-build/ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ # pytype static type analyzer .pytype/ # Cython debug symbols cython_debug/ # PyCharm # JetBrains specific template is maintained in a separate JetBrains.gitignore that can # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ # Ruff stuff: .ruff_cache/ # PyPI configuration file .pypirc uuid_extension-0.2.0/.github/0000775000175000017500000000000015115522155015415 5ustar edwardedwarduuid_extension-0.2.0/.github/copilot-testGeneration-instructions.md0000644000175000017500000000325113615410400025132 0ustar edwardedward# Test Generation Guidelines ## Test Organization - All test files should be placed in the `./tests/` directory - Name test files using the pattern: `test_{module_name}.py` (e.g., `test_utils.py`, or `test_subfolder_utils.py` if for files within subfolders) - Organize tests by module, with each module having its own test file ## Testing Framework - Use `pytest` as the primary testing framework - Leverage pytest fixtures when appropriate for test setup - Use parametrized tests for testing multiple input/output combinations ## Test Structure - Use descriptive class names that clearly state the test case purpose - Follow the AAA (Arrange, Act, Assert) pattern for all test cases: 1. **Arrange**: Set up test prerequisites and inputs 2. **Act**: Execute the functionality being tested 3. **Assert**: Verify the expected behavior occurred ## Example Test Structure ```python # Example test file: ./tests/test_example_module.py import pytest from uuid_extension import example_module class TestExampleFunctionality: def test_should_perform_expected_behavior_when_given_valid_input(self): # Arrange test_input = "valid_input" expected_output = "expected_result" # Act actual_output = example_module.function_under_test(test_input) # Assert assert actual_output == expected_output ``` ## Best Practices - Write tests before implementing functionality (TDD) when possible - Each test should focus on testing a single behavior - Create separate test classes for different groups of functionality - Keep tests independent and avoid dependencies between tests - Use meaningful assertions that clearly communicate the expected behavior uuid_extension-0.2.0/.github/copilot-codeGeneration-instructions.md0000644000175000017500000000554113615410400025071 0ustar edwardedward# GitHub Copilot Code Generation Instructions ## Python Code Style: `.py` Files - Follow these guidelines for all Python files. ### General - Minimum Python Version: `3.10`. ### Formatting - Adhere to the `PEP8` standard. - Use `snake_case` for variable and function names. - Use `PascalCase` for class names. - Enclose strings in `double quotes`. - Indent code using `4 spaces`. - Use `typing` annotations wherever possible. Prefer built-in types (e.g., `list`, `dict`, `tuple`) over imports from the `typing` module. - Avoid unnecessary blank lines and trailing whitespace. - Limit line length to `80 characters`. Use line breaks for longer lines, maintaining proper indentation. - Ensure consistent formatting across the codebase for readability and maintainability. - Regularly review and update formatting rules to align with evolving project requirements. ### Linting - Use `ruff` as the primary linter. - Check for `[tool.ruff.lint]` entries in `pyproject.toml` or rules in `ruff.toml`. - Follow rule `EM101`: Exception messages must not use string literals directly, assign to a variable first. - Resolve all linting violations before committing code. - If `ruff` is unavailable, use an alternative linter that supports `PEP8` compliance. - Regularly update linting configurations to align with project standards. - Document custom linting rules or exceptions in the repository. ### Example ```python def calculate_average(numbers: list[float]) -> float: """ Calculate the average of a list of numbers. Args: numbers: List of numerical values Returns: The average of the input numbers Raises: ValueError: If the list is empty """ if not numbers: msg = "Cannot calculate average of empty list" raise ValueError(msg) return sum(numbers) / len(numbers) ``` --- ## SQL Code Style: `.sql` Files - Use these guidelines for all SQL files. - Dialect: `TSQL` for Microsoft SQL Server. ### Formatting - Use `snake_case` for variable names. - Write `comma-first` lines. - Use UPPERCASE for SQL keywords (e.g., SELECT, FROM, WHERE). - Indent with `4 spaces`, not tabs. - Add line breaks before each clause (e.g., WHERE, JOIN, GROUP BY). - Use short but meaningful aliases for table names. - Include the schema name when referencing tables (e.g., `dbo.table_name`). - Add comments for complex logic or non-obvious operations. - Align similar elements vertically for better readability. #### Example: Comma-First Style ```sql SELECT column_id , column_name FROM dbo.mytable WHERE 1=1 AND column_id = 1 ``` --- ## Markdown Style: `.md` Files - Improve grammar and clarity when using `/fix` or `improve` commands. - Ensure concise and professional language. - Use proper headings and formatting for readability. - Avoid redundant or overly complex phrasing. - Regularly review and refine content for accuracy and consistency.uuid_extension-0.2.0/.github/copilot-commitMessageGeneration-instructions.md0000644000175000017500000000262513615410400026754 0ustar edwardedward# GitHub Copilot Commit Message Guidelines Generate commit messages following these strict guidelines: ## Format Always use the Conventional Commits format: ``` ():