Metadata-Version: 2.4
Name: com7-rpa-core
Version: 0.3.1
Summary: Reusable core utilities for COM7 Python RPA and automation projects.
Author: Suradath Bangnikrai
License-Expression: MIT
Keywords: rpa,automation,sql-server,credentials,configuration,logging,retry,diagnostics,com7
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: keyring<27,>=25.0
Requires-Dist: pyodbc<6,>=5.0
Requires-Dist: python-dotenv<2,>=1.0
Requires-Dist: requests<3,>=2.32
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: twine>=6.0; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-cov>=5.0; extra == "dev"
Requires-Dist: ruff>=0.9; extra == "dev"
Requires-Dist: mkdocs<2,>=1.6; extra == "dev"
Requires-Dist: mkdocs-material<10,>=9.6; extra == "dev"
Requires-Dist: mkdocstrings[python]<1,>=0.30; extra == "dev"
Dynamic: license-file

# COM7 RPA Core

`com7-rpa-core` is a reusable Python foundation for COM7 RPA and
automation projects.

Version **0.2.0** expands the original Database + Credentials package
into a common runtime foundation so individual RPA projects do not need
to repeatedly implement configuration loading, logging, retry behavior,
diagnostics, credential access, and SQL Server connectivity.

> Alpha release: public APIs may still evolve before 1.0.0.

## What v0.2.0 provides

  -----------------------------------------------------------------------
  Module                              Purpose
  ----------------------------------- -----------------------------------
  `com7_rpa_core.credentials`         Secure credential storage and
                                      retrieval through the
                                      operating-system keyring

  `com7_rpa_core.db`                  SQL Server configuration, automatic
                                      ODBC driver discovery, queries,
                                      scalar operations, execution,
                                      transactions, and health checks

  `com7_rpa_core.config`              Shared application/database
                                      configuration and `.env` loading

  `com7_rpa_core.logger`              Consistent logging for every RPA
                                      project

  `com7_rpa_core.retry`               Reusable retry behavior for
                                      transient operations

  `com7_rpa_core.diagnostics`         Structured error diagnostics with
                                      sensitive-value redaction

  `com7_rpa_core.errors`              Common exception hierarchy shared
                                      by core modules
  -----------------------------------------------------------------------

The long-term direction is to make COM7 RPA Core the reusable layer
underneath COM7 automation projects. Future modules can add shared
capabilities such as API clients, email, files, browser automation, OCR,
VPN/network helpers, notifications, and job/runtime utilities without
forcing every project to reimplement them.

## Requirements

-   Python 3.11+
-   Windows is the primary supported operating system for the current
    release.
-   Microsoft SQL Server access requires a compatible installed ODBC
    driver.
-   The library discovers installed SQL Server ODBC drivers dynamically;
    it is not hard-coded to Driver 17 or Driver 18.
-   `keyring` normally stores secrets in Windows Credential Manager on
    Windows.

## Installation

### From PyPI

When the production PyPI release is available:

``` powershell
pip install com7-rpa-core
```

Install a specific version:

``` powershell
pip install com7-rpa-core==0.2.0
```

Upgrade:

``` powershell
pip install --upgrade com7-rpa-core
```

### From TestPyPI

``` powershell
pip install `
  --index-url https://test.pypi.org/simple/ `
  --extra-index-url https://pypi.org/simple `
  com7-rpa-core==0.2.0
```

### Local development

``` powershell
py -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```

Verify the installed version:

``` powershell
python -c "import com7_rpa_core; print(com7_rpa_core.__version__)"
```

Expected:

``` text
0.2.0
```

## Recommended project usage

A consuming RPA project should depend on the library instead of copying
common utility code into the project.

Example:

``` text
my-rpa-project/
├── app/
│   ├── main.py
│   └── jobs/
├── .env
├── requirements.txt
└── README.md
```

`requirements.txt`:

``` text
com7-rpa-core==0.2.0
```

The project then imports only the shared capabilities it needs.

## Credentials

### Credential CLI

``` powershell
com7-rpa-cred set RPA_DB --username ERP_Nui
com7-rpa-cred get RPA_DB
com7-rpa-cred import credentials.csv
com7-rpa-cred delete RPA_DB
```

Passwords entered by `set` are hidden. `get` intentionally reports only
whether a password exists.

### Save a credential from Python

``` python
from com7_rpa_core.credentials import save_credential

save_credential("RPA_DB", "ERP_Nui", "your-password")
```

Prefer the CLI or an interactive workflow for real secrets so passwords
are not committed in source code.

### Read a credential

``` python
from com7_rpa_core.credentials import get_credential

username, password = get_credential("RPA_DB")
```

### Import credentials from CSV

Example local `credentials.csv`:

``` csv
key,username,password
RPA_DB,ERP_Nui,secret1
SCB_CORPORATE,myuser,secret2
```

Import:

``` powershell
com7-rpa-cred import credentials.csv
```

or:

``` python
from com7_rpa_core.credentials import import_credentials_csv

count = import_credentials_csv("credentials.csv")
print(count)
```

Do not commit plaintext credential CSV files. Delete them after import
when they contain real secrets.

## SQL Server

### Automatic ODBC driver discovery

List every ODBC driver visible to `pyodbc`:

``` powershell
python -c "from com7_rpa_core.db import get_installed_odbc_drivers; print('\n'.join(get_installed_odbc_drivers()))"
```

List drivers recognized as SQL Server drivers:

``` powershell
python -c "from com7_rpa_core.db import get_sql_server_drivers; print('\n'.join(get_sql_server_drivers()))"
```

Show the preferred detected SQL Server driver:

``` powershell
python -c "from com7_rpa_core.db import detect_sql_server_driver; print(detect_sql_server_driver())"
```

The library evaluates installed SQL Server drivers dynamically and
prefers the most appropriate available candidate. A caller can still
explicitly configure a driver when a particular environment requires it.

### Database health check using a stored credential

``` python
from com7_rpa_core.db import SqlServerConfig, SqlServerDatabase

config = SqlServerConfig.from_credential(
    server=r"LOVELYDOG\LOVELYCAT",
    database="RPA",
    credential_key="RPA_DB",
    encrypt=True,
    trust_server_certificate=False,
)

db = SqlServerDatabase(config)
result = db.health_check()

print(result)
```

Example fields returned by the health check include:

``` text
server_name
database_name
login_name
current_time
```

### Parameterized query

``` python
rows = db.query(
    "SELECT TOP 10 * FROM dbo.MyTable WHERE company = ?",
    ("GI01",),
)
```

Always parameterize values instead of concatenating user or external
data into SQL.

### Scalar query

``` python
count = db.scalar(
    "SELECT COUNT(*) FROM dbo.MyTable WHERE company = ?",
    ("GI01",),
)
```

### Execute

``` python
affected = db.execute(
    "UPDATE dbo.MyTable SET status = ? WHERE id = ?",
    ("Y", 1001),
)
```

### Transaction

``` python
with db.transaction() as conn:
    cursor = conn.cursor()

    cursor.execute(
        "UPDATE dbo.MyTable SET status = ? WHERE id = ?",
        ("Y", 1001),
    )

    cursor.execute(
        "INSERT INTO dbo.AuditLog(reference_id, action) VALUES (?, ?)",
        (1001, "UPDATED"),
    )
```

The transaction commits when the block completes successfully and rolls
back when an exception escapes the block.

### Integration tests

``` powershell
python examples\db_health.py
python examples\db_full_test.py
```

`db_full_test.py` validates the real SQL Server path including health
check, parameterized query, scalar query, commit, and rollback.

## Configuration

Version 0.2.0 introduces shared configuration support, including `.env`
loading through `python-dotenv`.

Example import:

``` python
from com7_rpa_core.config import DatabaseSettings
```

A consuming project can keep environment-specific values outside
application source code and combine configuration with credential keys
instead of embedding passwords.

Recommended `.env` pattern:

``` dotenv
RPA_DB_SERVER=YOUR_SERVER
RPA_DB_DATABASE=RPA
RPA_DB_CREDENTIAL_KEY=RPA_DB
RPA_DB_ENCRYPT=true
RPA_DB_TRUST_SERVER_CERTIFICATE=false
RPA_DB_CONNECT_RETRIES=3
```

Do not commit real `.env` files. Commit `.env.example` with safe
placeholders instead.

## Logging

Create a consistent logger:

``` python
from com7_rpa_core.logger import get_logger

log = get_logger("MY-RPA")
log.info("Job started")
log.warning("Temporary condition detected")
log.error("Job failed")
```

Example output:

``` text
2026-08-27 14:27:05 | INFO | MY-RPA | Job started
```

This gives COM7 RPA projects a consistent log format instead of each
project configuring logging differently.

## Retry

The retry module centralizes retry behavior for transient failures so
every project does not need to write its own retry loop.

Use retry only for operations that can reasonably succeed on a later
attempt, such as temporary network/database availability. Do not use
retry to hide permanent configuration, authentication, validation, or
programming errors.

Database connection logic in v0.2.0 uses the common retry mechanism and
logs retry attempts consistently.

## Common errors

Core exceptions are available from `com7_rpa_core.errors`.

Example:

``` python
from com7_rpa_core.errors import Com7RpaError, DatabaseError

try:
    ...
except DatabaseError as exc:
    ...
except Com7RpaError as exc:
    ...
```

Module-specific errors inherit from the common COM7 RPA error hierarchy
where appropriate, allowing projects to catch either a specific failure
or a broader core-library failure.

## Diagnostics

Diagnostics capture structured failure information that can be saved for
investigation.

Example:

``` python
from com7_rpa_core.diagnostics import build_diagnostic, save_diagnostic

try:
    raise RuntimeError("Example RPA failure")
except Exception as exc:
    diagnostic = build_diagnostic(
        exc,
        context={
            "job": "COM7_TEST",
            "module": "example",
            "server": "192.168.43.84",
            "database": "RPA",
            "password": "do-not-expose",
            "api_token": "do-not-expose",
        },
    )

    path = save_diagnostic(
        diagnostic,
        "logs/diagnostics/example-error.json",
    )

    print(path)
```

Sensitive context fields such as passwords and tokens are redacted
before diagnostic output is written.

Run the included example:

``` powershell
python examples\diagnostics_example.py
```

## Suggested application pattern

A normal RPA project can combine the modules like this:

``` python
from com7_rpa_core.db import SqlServerConfig, SqlServerDatabase
from com7_rpa_core.logger import get_logger

log = get_logger("MY-RPA")

config = SqlServerConfig.from_credential(
    server=r"YOUR_SERVER",
    database="RPA",
    credential_key="RPA_DB",
    encrypt=True,
    trust_server_certificate=False,
)

db = SqlServerDatabase(config)

log.info("Starting job")

health = db.health_check()
log.info("Connected to %s / %s", health["server_name"], health["database_name"])

rows = db.query(
    "SELECT TOP 10 * FROM dbo.MyTable WHERE status = ?",
    ("PENDING",),
)

log.info("Loaded %s row(s)", len(rows))
```

The project owns its business process. COM7 RPA Core owns reusable
infrastructure behavior.

## Security practices

-   Never hard-code production passwords, API tokens, or private keys in
    Python files.
-   Store secrets through the credential module/keyring.
-   Do not commit `credentials.csv`, `.env`, diagnostic dumps containing
    unreviewed context, or other secret files.
-   Use parameterized SQL.
-   Keep TLS verification enabled whenever the server environment
    supports a trusted certificate.
-   Use `trust_server_certificate=True` only when the environment
    explicitly requires it and the security implications are understood.
-   Review diagnostic context before adding new fields; sensitive names
    are redacted, but projects should still avoid passing unnecessary
    secrets.
-   Pin a known library version in production RPA projects.

## Testing

Run the complete unit-test suite:

``` powershell
pytest
```

Run linting:

``` powershell
ruff check .
```

Current v0.2.0 development validation includes the credentials, database
configuration/driver detection, logging/error, retry, and diagnostics
behavior.

For a real database integration test:

``` powershell
python examples\db_full_test.py
```

## Release validation

Before building a release:

``` powershell
ruff check .
pytest
python examples\db_full_test.py
python examples\diagnostics_example.py
```

Clean previous build artifacts:

``` powershell
Remove-Item -Recurse -Force build -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force dist -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force src\com7_rpa_core.egg-info -ErrorAction SilentlyContinue
```

Build and validate:

``` powershell
python -m build
python -m twine check dist/*
```

## Publish to TestPyPI

``` powershell
python -m twine upload --repository testpypi dist/*
```

Then test the exact built release in a fresh environment:

``` powershell
py -m venv .venv-testpypi
.\.venv-testpypi\Scripts\Activate.ps1

python -m pip install --upgrade pip

pip install `
  --index-url https://test.pypi.org/simple/ `
  --extra-index-url https://pypi.org/simple `
  com7-rpa-core==0.2.0

python -c "import com7_rpa_core; print(com7_rpa_core.__version__)"
```

## Publish to production PyPI

After TestPyPI installation and smoke tests pass:

``` powershell
python -m twine upload dist/*
```

Consumers can then install:

``` powershell
pip install com7-rpa-core==0.2.0
```

## Versioning

COM7 RPA Core follows Semantic Versioning.

-   `0.1.x` --- initial Database + Credentials foundation and bug fixes.
-   `0.2.x` --- common runtime foundation: configuration, logging,
    retry, diagnostics, common errors, and stronger SQL Server driver
    handling.
-   Future `0.x` releases --- additional reusable RPA capability modules
    while the public API is still evolving.
-   `1.0.0` --- stable public API baseline.

When a project needs reproducibility, pin the exact version:

``` text
com7-rpa-core==0.2.0
```

When testing compatibility with a future compatible range, use an
explicit range according to the project's release policy.

## Development workflow

Recommended release sequence:

``` text
change code
    ↓
add/update tests
    ↓
ruff check .
    ↓
pytest
    ↓
integration tests
    ↓
update README + CHANGELOG
    ↓
clean build artifacts
    ↓
python -m build
    ↓
python -m twine check dist/*
    ↓
TestPyPI
    ↓
fresh-environment install test
    ↓
Git commit/tag
    ↓
production PyPI
```

## Roadmap

The package is intentionally being built in layers.

Current foundation:

``` text
COM7 RPA Core
├── Credentials
├── Configuration
├── Logging
├── Errors
├── Retry
├── Diagnostics
└── Database
```

Planned reusable capability areas can include:

``` text
COM7 RPA Core
├── API / HTTP
├── Email
├── Files / Excel / CSV
├── Browser / Selenium
├── OCR / Document extraction
├── VPN / Network
├── Notifications
├── Job execution / status
├── Scheduling helpers
└── Additional enterprise integrations
```

New modules should be added when they represent repeated infrastructure
behavior across projects. Project-specific business logic should remain
in the individual RPA project.

## License

MIT.

## v0.3 Phase 2 - Email

The Email module provides reusable SMTP delivery with text/HTML alternatives, TO/CC/BCC, attachments, inline images, STARTTLS/SSL, OS credentials, environment configuration, retry handling and reusable templates.

```python
from com7_rpa_core.mail import MailClient

mail = MailClient.from_env(prefix="RPA_MAIL")
mail.send_template(
    to="manager@example.com",
    template="success",
    data={
        "brand": "COM7 RPA",
        "title": "DMS PO completed",
        "message": "All pending records were processed.",
        "process": "DMS PO",
        "reference": "BATCH-001",
        "timestamp": "2026-08-28T12:00:00+07:00",
        "footer": "Generated automatically by COM7 RPA Core.",
    },
)
```

See `docs/email.md` for the complete guide.
