# Port Experience
A Python middleware service for managing [Port.io](https://www.getport.io/) resources including blueprints, actions, mappings, and widgets. This tool provides an interactive CLI to create, update, and synchronize Port.io configurations from local JSON files.
## Features
- 🎯 **Multi-Resource Management**: Handle blueprints, actions, mappings, and widgets
- 🔄 **Intelligent Sync**: Compare local resources with existing Port.io resources
- ✅ **Interactive Confirmation**: Review and confirm changes before applying them
- 🛡️ **Safe Merge Strategy**: Update existing resources without losing data
- 📊 **Detailed Reporting**: Clear summary of operations and their outcomes
- 🔧 **Flexible Configuration**: Control which resources to process via environment variables
## Architecture
The project is organized into specialized managers:
- **`BasePortManager`**: Shared authentication and API request handling
- **`PortBlueprintManager`**: Manages Port.io blueprints
- **`PortActionManager`**: Manages Port.io actions
- **`PortMappingManager`**: Manages Port.io integrations and mappings
- **`PortWidgetManager`**: Manages Port.io dashboard widgets
- **`BlueprintTreeManager`**: Handles blueprint dependency resolution
## Quick Start
### Prerequisites
- Python 3.10 or higher
- Port.io account with API credentials (Client ID and Client Secret)
### Installation
**Option 1: Install from PyPI (recommended)**
```bash
pip install port-experience
```
**Option 2: Install from source**
1. **Clone the repository**:
```bash
git clone https://github.com/port-experimental/one-click-port-experience
cd one-click-port-experience
```
2. **Create a virtual environment** (recommended):
```bash
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
```
3. **Install dependencies**:
```bash
pip install -r requirements.txt
```
4. **Install package in development mode**:
```bash
pip install -e .
```
5. **Configure environment variables**:
Create a `.env` file in the project root:
```bash
PORT_CLIENT_ID=your_client_id_here
PORT_CLIENT_SECRET=your_client_secret_here
# Optional: Customize directories
BLUEPRINTS_DIR=setup/blueprints
ACTIONS_DIR=setup/actions
MAPPINGS_DIR=setup/mappings
WIDGETS_DIR=setup/widgets
# Optional: Specify which resources to process
ACTION=all # Options: blueprints, actions, mappings, widgets, all
# Optional: Define which folders are required
EXPECTED_FOLDERS=blueprints,actions,widgets # Comma-separated list
# Optional: Set log level
LOG_LEVEL=INFO # Options: DEBUG, INFO, WARNING, ERROR
```
**Getting Port.io Credentials**:
- Log in to your Port.io account
- Navigate to Settings → Credentials
- Create a new API client or use existing credentials
- Copy the Client ID and Client Secret
### Usage
**Recommended: Install and use the CLI**
```bash
# Install the package
pip install port-experience
# Apply all configurations
experience apply
```
**Alternative: Run from source**
```bash
# Activate virtual environment
source .venv/bin/activate
# Install in development mode
pip install -e .
# Run using the CLI command
experience apply
```
The tool will:
1. 🔍 Scan local JSON files in the `setup/` directories
2. 📋 Compare them with existing resources in Port.io
3. 📊 Display a summary of changes (new vs. updates)
4. ⚠️ Ask for confirmation before proceeding
5. 🚀 Create/update resources based on your confirmation
6. ✅ Report the results
### Programmatic Usage
You can also use the managers programmatically in your Python code:
```python
from port_experience import PortBlueprintManager, PortActionManager
# Initialize managers
blueprint_manager = PortBlueprintManager(
client_id="your_client_id",
client_secret="your_client_secret"
)
action_manager = PortActionManager(
client_id="your_client_id",
client_secret="your_client_secret"
)
# Setup blueprints from directory
blueprint_results = blueprint_manager.setup_all_blueprints("setup/blueprints")
# Setup actions from directory
action_results = action_manager.setup_all_actions("setup/actions")
# Check if specific resources exist
if blueprint_manager.blueprint_exists("my_blueprint"):
print("Blueprint exists!")
if action_manager.action_exists("my_action"):
print("Action exists!")
```
### Processing Specific Resources
Currently, the CLI processes all resource types by default. For more granular control, you can modify the source code or use environment variables:
```bash
# The CLI will process all resources by default
experience apply
# For development/testing with specific resource types,
# you can modify the source code or use environment variables
```
## Project Structure
```
one-click-port-experience/
├── pyproject.toml # Python package configuration
├── requirements.txt # Python dependencies
├── README.md # This file
├── .env # Environment configuration (create this)
├── .gitignore # Git ignore patterns
├── port_experience/ # Main package directory
│ ├── __init__.py # Package initialization and exports
│ ├── main.py # Main entry point and orchestration
│ └── managers/ # Resource managers
│ ├── __init__.py # Base manager class
│ ├── action_manager.py # Action resource manager
│ ├── blueprint_manager.py # Blueprint resource manager
│ ├── blueprint_tree_manager.py # Blueprint dependency manager
│ ├── mapping_manager.py # Mapping/integration manager
│ └── widget_manager.py # Widget/dashboard manager
└── setup/ # Resource definitions (JSON files)
├── blueprints/ # Blueprint JSON files
├── actions/ # Action JSON files
├── mappings/ # Mapping JSON files
└── widgets/ # Widget JSON files
```
## Configuration
### Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `PORT_CLIENT_ID` | ✅ | - | Port.io API Client ID |
| `PORT_CLIENT_SECRET` | ✅ | - | Port.io API Client Secret |
| `BLUEPRINTS_DIR` | ❌ | `setup/blueprints` | Path to blueprints directory |
| `ACTIONS_DIR` | ❌ | `setup/actions` | Path to actions directory |
| `MAPPINGS_DIR` | ❌ | `setup/mappings` | Path to mappings directory |
| `WIDGETS_DIR` | ❌ | `setup/widgets` | Path to widgets directory |
| `ACTION` | ❌ | `all` | Resource types to process |
| `EXPECTED_FOLDERS` | ❌ | `blueprints,actions,mappings,widgets` | Required directories |
| `LOG_LEVEL` | ❌ | `INFO` | Logging verbosity level |
### Resource JSON Format
Each resource type expects JSON files in a specific format. Here are examples:
**Blueprint** (`setup/blueprints/example.json`):
```json
{
"identifier": "my_blueprint",
"title": "My Blueprint",
"icon": "Microservice",
"schema": {
"properties": {
"name": {
"type": "string",
"title": "Name"
}
}
}
}
```
**Action** (`setup/actions/example.json`):
```json
{
"identifier": "my_action",
"title": "My Action",
"icon": "Github",
"blueprint": "my_blueprint",
"invocationMethod": {
"type": "WEBHOOK"
}
}
```
## How It Works
### 1. Resource Discovery
The tool scans the configured directories for JSON files containing resource definitions.
### 2. Comparison & Analysis
For each local resource, the tool:
- Checks if it already exists in Port.io
- Determines if it needs to be created or updated
- Identifies any additional resources in Port.io not in local files
### 3. User Confirmation
Before making any changes, the tool displays:
- Resources to be created (🆕)
- Resources to be updated (🔄)
- Total operation summary
### 4. Merge Strategy
The tool uses a **merge strategy** when updating resources:
- Existing properties are preserved
- New properties are added
- Changed properties are updated
- No data is deleted
### 5. Execution & Reporting
After confirmation, the tool:
- Processes each resource
- Reports success/failure for each operation
- Provides a final summary
## Manager Classes
### BasePortManager
Located in `managers/__init__.py`, provides:
- Authentication with Port.io API
- Access token management
- Generic API request methods
- JSON file discovery
- Logging configuration
### PortBlueprintManager
Manages Port.io blueprints:
- Create and update blueprints
- Check blueprint existence
- Handle blueprint dependencies
### PortActionManager
Manages Port.io actions:
- Create and update actions
- Validate action configurations
- Link actions to blueprints
### PortMappingManager
Manages Port.io integrations:
- Create and update mappings
- Handle integration configurations
### PortWidgetManager
Manages Port.io dashboard widgets:
- Create and update pages/widgets
- Configure dashboard layouts
### BlueprintTreeManager
Handles blueprint dependencies:
- Parse blueprint relationships
- Resolve dependency order
- Build blueprint hierarchy trees
## Error Handling
The tool includes comprehensive error handling:
- **Missing Credentials**: Clear error if Port.io credentials are not provided
- **API Failures**: Detailed logging of API errors with status codes
- **Invalid JSON**: Reports which files have syntax errors
- **Missing Directories**: Configurable whether to treat as error or skip
- **Failed Operations**: Continues processing other resources, reports failures at the end
## Logging
Configure logging verbosity with the `LOG_LEVEL` environment variable:
```bash
LOG_LEVEL=DEBUG experience apply # Detailed debug information
LOG_LEVEL=INFO experience apply # Standard information (default)
LOG_LEVEL=WARNING experience apply # Only warnings and errors
LOG_LEVEL=ERROR experience apply # Only errors
```
## Development
### Adding New Resource Types
1. Create a new manager class inheriting from `BasePortManager`
2. Implement resource-specific methods
3. Add the resource type to `main.py`
4. Create corresponding directory in `setup/`
### Running Tests
```bash
# Add your test commands here
pytest tests/
```
## Troubleshooting
### Authentication Failures
```
Error: Authentication failed: 401
```
**Solution**: Verify your `PORT_CLIENT_ID` and `PORT_CLIENT_SECRET` are correct.
### Missing Resources
```
Error: Required blueprints directory 'setup/blueprints' not found
```
**Solution**: Create the directory or update `BLUEPRINTS_DIR` in `.env`.
### API Rate Limits
If you encounter rate limiting, the tool will log the error. Wait a moment and retry.
### JSON Syntax Errors
```
Error: Invalid JSON in example.json: Expecting ',' delimiter
```
**Solution**: Validate your JSON files using a JSON validator.
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
[Add your license here]
## Support
For issues, questions, or contributions:
- Open an issue in the repository
- Contact the development team
- Check Port.io documentation: https://docs.getport.io/
## Acknowledgments
Built for seamless integration with [Port.io](https://www.getport.io/) - The Internal Developer Portal.
Raw data
{
"_id": null,
"home_page": null,
"name": "port-experience",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": "Erioluwa Asiru <eri.asiru@port.io>",
"keywords": "port, port.io, getport, internal-developer-portal, idp, blueprints, middleware, devops, platform-engineering",
"author": null,
"author_email": "CS - SA TEAM <cs-sa@port.io>",
"download_url": "https://files.pythonhosted.org/packages/6a/93/fb8a8bc8126bb9ea909b201cfd840881abba7e860057136fad9c33513013/port_experience-0.1.2.tar.gz",
"platform": null,
"description": "# Port Experience\n\nA Python middleware service for managing [Port.io](https://www.getport.io/) resources including blueprints, actions, mappings, and widgets. This tool provides an interactive CLI to create, update, and synchronize Port.io configurations from local JSON files.\n\n## Features\n\n- \ud83c\udfaf **Multi-Resource Management**: Handle blueprints, actions, mappings, and widgets\n- \ud83d\udd04 **Intelligent Sync**: Compare local resources with existing Port.io resources\n- \u2705 **Interactive Confirmation**: Review and confirm changes before applying them\n- \ud83d\udee1\ufe0f **Safe Merge Strategy**: Update existing resources without losing data\n- \ud83d\udcca **Detailed Reporting**: Clear summary of operations and their outcomes\n- \ud83d\udd27 **Flexible Configuration**: Control which resources to process via environment variables\n\n## Architecture\n\nThe project is organized into specialized managers:\n\n- **`BasePortManager`**: Shared authentication and API request handling\n- **`PortBlueprintManager`**: Manages Port.io blueprints\n- **`PortActionManager`**: Manages Port.io actions\n- **`PortMappingManager`**: Manages Port.io integrations and mappings\n- **`PortWidgetManager`**: Manages Port.io dashboard widgets\n- **`BlueprintTreeManager`**: Handles blueprint dependency resolution\n\n## Quick Start\n\n### Prerequisites\n\n- Python 3.10 or higher\n- Port.io account with API credentials (Client ID and Client Secret)\n\n### Installation\n\n**Option 1: Install from PyPI (recommended)**\n```bash\npip install port-experience\n```\n\n**Option 2: Install from source**\n1. **Clone the repository**:\n ```bash\n git clone https://github.com/port-experimental/one-click-port-experience\n cd one-click-port-experience\n ```\n\n2. **Create a virtual environment** (recommended):\n ```bash\n python -m venv .venv\n source .venv/bin/activate # On Windows: .venv\\Scripts\\activate\n ```\n\n3. **Install dependencies**:\n ```bash\n pip install -r requirements.txt\n ```\n\n4. **Install package in development mode**:\n ```bash\n pip install -e .\n ```\n\n5. **Configure environment variables**:\n \n Create a `.env` file in the project root:\n ```bash\n PORT_CLIENT_ID=your_client_id_here\n PORT_CLIENT_SECRET=your_client_secret_here\n \n # Optional: Customize directories\n BLUEPRINTS_DIR=setup/blueprints\n ACTIONS_DIR=setup/actions\n MAPPINGS_DIR=setup/mappings\n WIDGETS_DIR=setup/widgets\n \n # Optional: Specify which resources to process\n ACTION=all # Options: blueprints, actions, mappings, widgets, all\n \n # Optional: Define which folders are required\n EXPECTED_FOLDERS=blueprints,actions,widgets # Comma-separated list\n \n # Optional: Set log level\n LOG_LEVEL=INFO # Options: DEBUG, INFO, WARNING, ERROR\n ```\n\n **Getting Port.io Credentials**:\n - Log in to your Port.io account\n - Navigate to Settings \u2192 Credentials\n - Create a new API client or use existing credentials\n - Copy the Client ID and Client Secret\n\n### Usage\n\n**Recommended: Install and use the CLI**\n```bash\n# Install the package\npip install port-experience\n\n# Apply all configurations\nexperience apply\n```\n\n**Alternative: Run from source**\n```bash\n# Activate virtual environment\nsource .venv/bin/activate\n\n# Install in development mode\npip install -e .\n\n# Run using the CLI command\nexperience apply\n```\n\nThe tool will:\n1. \ud83d\udd0d Scan local JSON files in the `setup/` directories\n2. \ud83d\udccb Compare them with existing resources in Port.io\n3. \ud83d\udcca Display a summary of changes (new vs. updates)\n4. \u26a0\ufe0f Ask for confirmation before proceeding\n5. \ud83d\ude80 Create/update resources based on your confirmation\n6. \u2705 Report the results\n\n### Programmatic Usage\n\nYou can also use the managers programmatically in your Python code:\n\n```python\nfrom port_experience import PortBlueprintManager, PortActionManager\n\n# Initialize managers\nblueprint_manager = PortBlueprintManager(\n client_id=\"your_client_id\",\n client_secret=\"your_client_secret\"\n)\n\naction_manager = PortActionManager(\n client_id=\"your_client_id\", \n client_secret=\"your_client_secret\"\n)\n\n# Setup blueprints from directory\nblueprint_results = blueprint_manager.setup_all_blueprints(\"setup/blueprints\")\n\n# Setup actions from directory\naction_results = action_manager.setup_all_actions(\"setup/actions\")\n\n# Check if specific resources exist\nif blueprint_manager.blueprint_exists(\"my_blueprint\"):\n print(\"Blueprint exists!\")\n\nif action_manager.action_exists(\"my_action\"):\n print(\"Action exists!\")\n```\n\n### Processing Specific Resources\n\nCurrently, the CLI processes all resource types by default. For more granular control, you can modify the source code or use environment variables:\n\n```bash\n# The CLI will process all resources by default\nexperience apply\n\n# For development/testing with specific resource types,\n# you can modify the source code or use environment variables\n```\n\n## Project Structure\n\n```\none-click-port-experience/\n\u251c\u2500\u2500 pyproject.toml # Python package configuration\n\u251c\u2500\u2500 requirements.txt # Python dependencies\n\u251c\u2500\u2500 README.md # This file\n\u251c\u2500\u2500 .env # Environment configuration (create this)\n\u251c\u2500\u2500 .gitignore # Git ignore patterns\n\u251c\u2500\u2500 port_experience/ # Main package directory\n\u2502 \u251c\u2500\u2500 __init__.py # Package initialization and exports\n\u2502 \u251c\u2500\u2500 main.py # Main entry point and orchestration\n\u2502 \u2514\u2500\u2500 managers/ # Resource managers\n\u2502 \u251c\u2500\u2500 __init__.py # Base manager class\n\u2502 \u251c\u2500\u2500 action_manager.py # Action resource manager\n\u2502 \u251c\u2500\u2500 blueprint_manager.py # Blueprint resource manager\n\u2502 \u251c\u2500\u2500 blueprint_tree_manager.py # Blueprint dependency manager\n\u2502 \u251c\u2500\u2500 mapping_manager.py # Mapping/integration manager\n\u2502 \u2514\u2500\u2500 widget_manager.py # Widget/dashboard manager\n\u2514\u2500\u2500 setup/ # Resource definitions (JSON files)\n \u251c\u2500\u2500 blueprints/ # Blueprint JSON files\n \u251c\u2500\u2500 actions/ # Action JSON files\n \u251c\u2500\u2500 mappings/ # Mapping JSON files\n \u2514\u2500\u2500 widgets/ # Widget JSON files\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `PORT_CLIENT_ID` | \u2705 | - | Port.io API Client ID |\n| `PORT_CLIENT_SECRET` | \u2705 | - | Port.io API Client Secret |\n| `BLUEPRINTS_DIR` | \u274c | `setup/blueprints` | Path to blueprints directory |\n| `ACTIONS_DIR` | \u274c | `setup/actions` | Path to actions directory |\n| `MAPPINGS_DIR` | \u274c | `setup/mappings` | Path to mappings directory |\n| `WIDGETS_DIR` | \u274c | `setup/widgets` | Path to widgets directory |\n| `ACTION` | \u274c | `all` | Resource types to process |\n| `EXPECTED_FOLDERS` | \u274c | `blueprints,actions,mappings,widgets` | Required directories |\n| `LOG_LEVEL` | \u274c | `INFO` | Logging verbosity level |\n\n### Resource JSON Format\n\nEach resource type expects JSON files in a specific format. Here are examples:\n\n**Blueprint** (`setup/blueprints/example.json`):\n```json\n{\n \"identifier\": \"my_blueprint\",\n \"title\": \"My Blueprint\",\n \"icon\": \"Microservice\",\n \"schema\": {\n \"properties\": {\n \"name\": {\n \"type\": \"string\",\n \"title\": \"Name\"\n }\n }\n }\n}\n```\n\n**Action** (`setup/actions/example.json`):\n```json\n{\n \"identifier\": \"my_action\",\n \"title\": \"My Action\",\n \"icon\": \"Github\",\n \"blueprint\": \"my_blueprint\",\n \"invocationMethod\": {\n \"type\": \"WEBHOOK\"\n }\n}\n```\n\n## How It Works\n\n### 1. Resource Discovery\nThe tool scans the configured directories for JSON files containing resource definitions.\n\n### 2. Comparison & Analysis\nFor each local resource, the tool:\n- Checks if it already exists in Port.io\n- Determines if it needs to be created or updated\n- Identifies any additional resources in Port.io not in local files\n\n### 3. User Confirmation\nBefore making any changes, the tool displays:\n- Resources to be created (\ud83c\udd95)\n- Resources to be updated (\ud83d\udd04)\n- Total operation summary\n\n### 4. Merge Strategy\nThe tool uses a **merge strategy** when updating resources:\n- Existing properties are preserved\n- New properties are added\n- Changed properties are updated\n- No data is deleted\n\n### 5. Execution & Reporting\nAfter confirmation, the tool:\n- Processes each resource\n- Reports success/failure for each operation\n- Provides a final summary\n\n## Manager Classes\n\n### BasePortManager\nLocated in `managers/__init__.py`, provides:\n- Authentication with Port.io API\n- Access token management\n- Generic API request methods\n- JSON file discovery\n- Logging configuration\n\n### PortBlueprintManager\nManages Port.io blueprints:\n- Create and update blueprints\n- Check blueprint existence\n- Handle blueprint dependencies\n\n### PortActionManager\nManages Port.io actions:\n- Create and update actions\n- Validate action configurations\n- Link actions to blueprints\n\n### PortMappingManager\nManages Port.io integrations:\n- Create and update mappings\n- Handle integration configurations\n\n### PortWidgetManager\nManages Port.io dashboard widgets:\n- Create and update pages/widgets\n- Configure dashboard layouts\n\n### BlueprintTreeManager\nHandles blueprint dependencies:\n- Parse blueprint relationships\n- Resolve dependency order\n- Build blueprint hierarchy trees\n\n## Error Handling\n\nThe tool includes comprehensive error handling:\n\n- **Missing Credentials**: Clear error if Port.io credentials are not provided\n- **API Failures**: Detailed logging of API errors with status codes\n- **Invalid JSON**: Reports which files have syntax errors\n- **Missing Directories**: Configurable whether to treat as error or skip\n- **Failed Operations**: Continues processing other resources, reports failures at the end\n\n## Logging\n\nConfigure logging verbosity with the `LOG_LEVEL` environment variable:\n\n```bash\nLOG_LEVEL=DEBUG experience apply # Detailed debug information\nLOG_LEVEL=INFO experience apply # Standard information (default)\nLOG_LEVEL=WARNING experience apply # Only warnings and errors\nLOG_LEVEL=ERROR experience apply # Only errors\n```\n\n## Development\n\n### Adding New Resource Types\n\n1. Create a new manager class inheriting from `BasePortManager`\n2. Implement resource-specific methods\n3. Add the resource type to `main.py`\n4. Create corresponding directory in `setup/`\n\n### Running Tests\n\n```bash\n# Add your test commands here\npytest tests/\n```\n\n## Troubleshooting\n\n### Authentication Failures\n```\nError: Authentication failed: 401\n```\n**Solution**: Verify your `PORT_CLIENT_ID` and `PORT_CLIENT_SECRET` are correct.\n\n### Missing Resources\n```\nError: Required blueprints directory 'setup/blueprints' not found\n```\n**Solution**: Create the directory or update `BLUEPRINTS_DIR` in `.env`.\n\n### API Rate Limits\nIf you encounter rate limiting, the tool will log the error. Wait a moment and retry.\n\n### JSON Syntax Errors\n```\nError: Invalid JSON in example.json: Expecting ',' delimiter\n```\n**Solution**: Validate your JSON files using a JSON validator.\n\n## Contributing\n\nContributions are welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\n[Add your license here]\n\n## Support\n\nFor issues, questions, or contributions:\n- Open an issue in the repository\n- Contact the development team\n- Check Port.io documentation: https://docs.getport.io/\n\n## Acknowledgments\n\nBuilt for seamless integration with [Port.io](https://www.getport.io/) - The Internal Developer Portal.\n",
"bugtrack_url": null,
"license": null,
"summary": "A Python middleware service for managing Port.io resources including blueprints, actions, mappings, and widgets",
"version": "0.1.2",
"project_urls": {
"Source Code": "https://github.com/port-experimental/one-click-port-experience"
},
"split_keywords": [
"port",
" port.io",
" getport",
" internal-developer-portal",
" idp",
" blueprints",
" middleware",
" devops",
" platform-engineering"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "31fbc3c7c922aff5ec50564e7cfe16169296f67f3a0d780ae552e8671f7765a1",
"md5": "cc6d52f65ee78251eaa37fb95787d26f",
"sha256": "46c9944c587f48231d80819c2a2f208345a6f41d11be10dd7d0d6397b2a974de"
},
"downloads": -1,
"filename": "port_experience-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cc6d52f65ee78251eaa37fb95787d26f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 33130,
"upload_time": "2025-10-14T11:12:58",
"upload_time_iso_8601": "2025-10-14T11:12:58.063748Z",
"url": "https://files.pythonhosted.org/packages/31/fb/c3c7c922aff5ec50564e7cfe16169296f67f3a0d780ae552e8671f7765a1/port_experience-0.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "6a93fb8a8bc8126bb9ea909b201cfd840881abba7e860057136fad9c33513013",
"md5": "bb096f2ec78f254c810a15f745a9bdf1",
"sha256": "b78b9d9eaed94652f35c7ddac3f38fecefcb73fcdc9de11165b0d766a6db503f"
},
"downloads": -1,
"filename": "port_experience-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "bb096f2ec78f254c810a15f745a9bdf1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 26246,
"upload_time": "2025-10-14T11:12:59",
"upload_time_iso_8601": "2025-10-14T11:12:59.453840Z",
"url": "https://files.pythonhosted.org/packages/6a/93/fb8a8bc8126bb9ea909b201cfd840881abba7e860057136fad9c33513013/port_experience-0.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-14 11:12:59",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "port-experimental",
"github_project": "one-click-port-experience",
"github_not_found": true,
"lcname": "port-experience"
}