Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e9891c6
Bump pip from 21.1 to 23.3
dependabot[bot] Jun 18, 2024
2e8a382
Bump jinja2 from 2.11.3 to 3.1.4
dependabot[bot] Jun 18, 2024
ed158e9
Bump tqdm from 4.32.1 to 4.66.3
dependabot[bot] Jun 18, 2024
eda7f03
Bump cryptography from 42.0.8 to 43.0.1
dependabot[bot] Sep 4, 2024
46eab02
Merge pull request #59 from esper-io/dependabot/pip/jinja2-3.1.4
nazeel-esper Jun 4, 2025
82ea27b
Merge pull request #60 from esper-io/dependabot/pip/pip-23.3
nazeel-esper Jun 4, 2025
325f8a1
Merge pull request #61 from esper-io/dependabot/pip/tqdm-4.66.3
nazeel-esper Jun 4, 2025
e6d6453
Merge pull request #63 from esper-io/dependabot/pip/cryptography-43.0.1
nazeel-esper Jun 4, 2025
d84bc08
Bump cryptography from 43.0.1 to 44.0.1
dependabot[bot] Jun 4, 2025
00dd637
Bump jinja2 from 3.1.4 to 3.1.6
dependabot[bot] Jun 4, 2025
7e44554
fix: add support for new device states
nazeel-esper Jun 4, 2025
c958735
Merge pull request #65 from esper-io/dependabot/pip/jinja2-3.1.6
nazeel-esper Jun 4, 2025
8a44f13
Merge pull request #64 from esper-io/dependabot/pip/cryptography-44.0.1
nazeel-esper Jun 4, 2025
d2db5a9
Merge pull request #66 from esper-io/sync-device-states
nazeel-esper Jun 4, 2025
46c1c48
fix: esper-cli app version formate changes legacy support added
parthp-esper Jan 16, 2026
7c92d6e
Merge pull request #71 from esper-io/DSM-4831-SDK-CLI-app-version-for…
parthp-esper Jan 20, 2026
075b75e
fix: version update for sdk and cli
parthp-esper Jan 23, 2026
c70e794
Merge pull request #72 from esper-io/DSM-4831-SDK-CLI-app-version-for…
parthp-esper Jan 23, 2026
89a679e
version update
parthp-esper Jan 23, 2026
47938d1
Merge pull request #74 from esper-io/DSM-4831-SDK-CLI-app-version-for…
parthp-esper Jan 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,16 @@ Adds support for:
- Content Management

Updated dependencies

## 0.0.14

- Add support for new device states

## 0.0.15

- Added App version format changes (includes version_name and version_code)
- Added `legacy_format {true/false}` cmd arg for app version format chnages

## 0.0.16

- Updated requirements.txt (esperclient==0.1.3)
46 changes: 43 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ This package provides a unified command line interface to the Esper API Services
Current stable release versions are

API version: 1.0.0
SDK version: 0.1.2
CLI version: 0.0.13
SDK version: 0.1.3
CLI version: 0.0.16

## Requirements

Expand Down Expand Up @@ -769,7 +769,7 @@ category
content_rating 0.0
compatibility
```
Below example listing versions of current active app,
Below example listing versions of current active app (default legacy format),
```sh
$ espercli version list
Total Number of Versions: 1
Expand All @@ -778,6 +778,15 @@ ID VERSION CODE BUILD NUMBER SIZE IN
54436edb-9b43-4e2c-8107-2c6fa90e2a9e 6.4.5 189 9.36421 1
```

To use the new standardized format with `VERSION NAME` instead of `BUILD NUMBER`:
```sh
$ espercli version list --legacy-format false
Total Number of Versions: 1

ID VERSION NAME VERSION CODE SIZE IN MB RELEASE TRACK INSTALLED COUNT
54436edb-9b43-4e2c-8107-2c6fa90e2a9e 6.4.5 30204 9.36421 1
```

#### 7. unset-active
The unset-active sub command used to unset the current active application.
```sh
Expand Down Expand Up @@ -809,16 +818,28 @@ $ espercli version list [OPTIONS]
| --app, -a | | Application id (UUID) |
| --code, -c | | Filter by version code |
| --number, -n | | Filter by build number |
| --legacy-format, -lf |true | Use legacy format, choices are [true, false] |
| --json, -j | | Render result in JSON format |

##### Example
**Default behavior (legacy format):**
```sh
$ espercli version list -a 630dbfab-7d85-4f81-9f3b-ffb038b0df72
Total Number of Versions: 1

ID VERSION CODE BUILD NUMBER SIZE IN MB RELEASE TRACK INSTALLED COUNT
54436edb-9b43-4e2c-8107-2c6fa90e2a9e 6.4.5 189 9.36421 1
```

**New standardized format (with --legacy-format false):**
```sh
$ espercli version list -a 630dbfab-7d85-4f81-9f3b-ffb038b0df72 --legacy-format false
Total Number of Versions: 1

ID VERSION NAME VERSION CODE SIZE IN MB RELEASE TRACK INSTALLED COUNT
54436edb-9b43-4e2c-8107-2c6fa90e2a9e 6.4.5 30204 9.36421 1
```

For list of versions if active application is set,
```sh
$ espercli version list
Expand All @@ -828,6 +849,8 @@ ID VERSION CODE BUILD NUMBER SIZE IN
54436edb-9b43-4e2c-8107-2c6fa90e2a9e 6.4.5 189 9.36421 1
```

> **Note:** By default, the CLI uses legacy format (`--legacy-format true`) which displays `BUILD NUMBER` column. Use `--legacy-format false` to get the new standardized format with `VERSION NAME` column. The new format uses `version_name` (human-readable) and `version_code` (internal identifier) instead of the legacy `build_number` and `version_code` system.

#### 2. show
Show application version information, here version id (UUID) is required to show version information.
```sh
Expand All @@ -838,9 +861,11 @@ $ espercli version show [OPTIONS] [version-id]
| Name, shorthand | Default| Description|
| ------------- |:------:|:----------|
| --app, -a | | Application id (UUID) |
| --legacy-format, -lf |true | Use legacy format, choices are [true, false] |
| --json, -j | | Render result in JSON format |

##### Example
**Default behavior (legacy format):**
```sh
$ espercli version show -a 630dbfab-7d85-4f81-9f3b-ffb038b0df72 54436edb-9b43-4e2c-8107-2c6fa90e2a9e

Expand All @@ -853,6 +878,21 @@ release_track
installed_count 1
```

**New standardized format (with --legacy-format false):**
```sh
$ espercli version show -a 630dbfab-7d85-4f81-9f3b-ffb038b0df72 54436edb-9b43-4e2c-8107-2c6fa90e2a9e --legacy-format false

TITLE DETAILS
id 54436edb-9b43-4e2c-8107-2c6fa90e2a9e
version_name 6.4.5
version_code 30204
size_in_mb 9.36421394348145
release_track
installed_count 1
```

> **Note:** By default, the CLI uses legacy format (`--legacy-format true`) which displays `build_number`. Use `--legacy-format false` to get the new standardized format with `version_name` (human-readable version string) and `version_code` (internal unique identifier).

#### 3. delete
Delete sub command used to delete particular application version. Here, version id (UUID) is required to delete version. Application will be also deleted if application contains one version and unset active application if it is set as active
```sh
Expand Down
12 changes: 10 additions & 2 deletions esper/controllers/application/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,11 @@ def upload(self):
version = application.versions[0]
renderable.append({title: 'version_id', details: version.id})
renderable.append({title: 'version_code', details: version.version_code})
renderable.append({title: 'build_number', details: version.build_number})
# Show version_name if available (new format), otherwise fallback to build_number (legacy format)
if hasattr(version, 'version_name') and version.version_name:
renderable.append({title: 'version_name', details: version.version_name})
elif hasattr(version, 'build_number') and version.build_number:
renderable.append({title: 'build_number', details: version.build_number})

self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain")
else:
Expand All @@ -228,7 +232,11 @@ def upload(self):
version = application.versions[0]
renderable['version_id'] = version.id
renderable['version_code'] = version.version_code
renderable['build_number'] = version.build_number
# Show version_name if available (new format), otherwise fallback to build_number (legacy format)
if hasattr(version, 'version_name') and version.version_name:
renderable['version_name'] = version.version_name
elif hasattr(version, 'build_number') and version.build_number:
renderable['build_number'] = version.build_number

self.app.render(renderable, format=OutputFormat.JSON.value)

Expand Down
110 changes: 87 additions & 23 deletions esper/controllers/application/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ class Meta:
{'help': 'Build number',
'action': 'store',
'dest': 'build_number'}),
(['-lf', '--legacy-format'],
{'help': 'Use legacy format, choices are [true, false]',
'action': 'store',
'choices': ['true', 'false'],
'default': 'true',
'dest': 'legacy_format'}),
(['-l', '--limit'],
{'help': 'Number of results to return per page',
'action': 'store',
Expand Down Expand Up @@ -75,6 +81,10 @@ def list(self):
build_number = self.app.pargs.build_number
limit = self.app.pargs.limit
offset = self.app.pargs.offset

# Get legacy_format flag and convert to boolean
legacy_format_str = getattr(self.app.pargs, 'legacy_format', 'true')
legacy_format = (legacy_format_str == 'true')

kwargs = {}
if version_code:
Expand All @@ -86,7 +96,7 @@ def list(self):
try:
# Find application versions in an enterprise
response = application_client.get_app_versions(application_id, enterprise_id, limit=limit, offset=offset,
**kwargs)
legacy_format=legacy_format, **kwargs)
except ApiException as e:
self.app.log.error(f"[version-list] Failed to list applications: {e}")
self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n")
Expand All @@ -96,44 +106,80 @@ def list(self):
if not self.app.pargs.json:
versions = []

label = {
'id': "ID",
'version_code': "VERSION CODE",
'build_number': "BUILD NUMBER",
'size_in_mb': "SIZE IN MB",
'release_track': "RELEASE TRACK",
'installed_count': "INSTALLED COUNT",
}
# Determine which columns to show based on legacy_format
if legacy_format:
# Legacy format: show BUILD NUMBER
label = {
'id': "ID",
'version_code': "VERSION CODE",
'build_number': "BUILD NUMBER",
'size_in_mb': "SIZE IN MB",
'release_track': "RELEASE TRACK",
'installed_count': "INSTALLED COUNT",
}
else:
# New format: show VERSION NAME
label = {
'id': "ID",
'version_name': "VERSION NAME",
'version_code': "VERSION CODE",
'size_in_mb': "SIZE IN MB",
'release_track': "RELEASE TRACK",
'installed_count': "INSTALLED COUNT",
}

for version in response.results:
versions.append(
{
if legacy_format:
# Legacy format: use build_number
version_dict = {
label['id']: version.id,
label['version_code']: version.version_code,
label['build_number']: version.build_number,
label['build_number']: version.build_number if hasattr(version, 'build_number') and version.build_number else '',
label['size_in_mb']: version.size_in_mb,
label['release_track']: version.release_track,
label['installed_count']: version.installed_count if version.installed_count else 0
}
)
else:
# New format: use version_name
version_dict = {
label['id']: version.id,
label['version_name']: version.version_name if hasattr(version, 'version_name') and version.version_name else '',
label['version_code']: version.version_code,
label['size_in_mb']: version.size_in_mb,
label['release_track']: version.release_track,
label['installed_count']: version.installed_count if version.installed_count else 0
}
versions.append(version_dict)
self.app.render(versions, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain")
else:
versions = []
for version in response.results:
versions.append(
{
if legacy_format:
# Legacy format: include build_number
version_dict = {
'id': version.id,
'version_code': version.version_code,
'build_number': version.build_number,
'build_number': version.build_number if hasattr(version, 'build_number') and version.build_number else None,
'size_in_mb': version.size_in_mb,
'release_track': version.release_track,
'installed_count': version.installed_count if version.installed_count else 0
}
)
else:
# New format: include version_name
version_dict = {
'id': version.id,
'version_name': version.version_name if hasattr(version, 'version_name') and version.version_name else None,
'version_code': version.version_code,
'size_in_mb': version.size_in_mb,
'release_track': version.release_track,
'installed_count': version.installed_count if version.installed_count else 0
}
versions.append(version_dict)
self.app.render(versions, format=OutputFormat.JSON.value)

def _version_basic_response(self, version, format=OutputFormat.TABULATED):
valid_keys = ['id', 'version_code', 'build_number', 'size_in_mb', 'release_track']
def _version_basic_response(self, version, format=OutputFormat.TABULATED, legacy_format=True):
# Include both version_name and build_number in valid_keys for flexibility
valid_keys = ['id', 'version_code', 'version_name', 'build_number', 'size_in_mb', 'release_track']

if format == OutputFormat.JSON:
renderable = {k: v for k, v in version.to_dict().items() if k in valid_keys}
Expand All @@ -142,7 +188,15 @@ def _version_basic_response(self, version, format=OutputFormat.TABULATED):
else:
title = "TITLE"
details = "DETAILS"
renderable = [{title: k, details: v} for k, v in version.to_dict().items() if k in valid_keys]
# Filter based on legacy_format
if legacy_format:
# Legacy format: prioritize build_number
filtered_dict = {k: v for k, v in version.to_dict().items() if k in valid_keys and k != 'version_name'}
else:
# New format: prioritize version_name
filtered_dict = {k: v for k, v in version.to_dict().items() if k in valid_keys and k != 'build_number'}

renderable = [{title: k, details: v} for k, v in filtered_dict.items()]

if version:
renderable.append(
Expand All @@ -163,6 +217,12 @@ def _version_basic_response(self, version, format=OutputFormat.TABULATED):
{'help': 'Application id',
'action': 'store',
'dest': 'application'}),
(['-lf', '--legacy-format'],
{'help': 'Use legacy format, choices are [true, false]',
'action': 'store',
'choices': ['true', 'false'],
'default': 'true',
'dest': 'legacy_format'}),
(['-j', '--json'],
{'help': 'Render result in Json format',
'action': 'store_true',
Expand All @@ -188,18 +248,22 @@ def show(self):

application_id = application.get('id')

# Get legacy_format flag and convert to boolean
legacy_format_str = getattr(self.app.pargs, 'legacy_format', 'true')
legacy_format = (legacy_format_str == 'true')

try:
response = application_client.get_app_version(version_id, application_id, enterprise_id)
response = application_client.get_app_version(version_id, application_id, enterprise_id, legacy_format=legacy_format)
except ApiException as e:
self.app.log.error(f"[version-show] Failed to show details of an version: {e}")
self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n")
return

if not self.app.pargs.json:
renderable = self._version_basic_response(response)
renderable = self._version_basic_response(response, format=OutputFormat.TABULATED, legacy_format=legacy_format)
self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain")
else:
renderable = self._version_basic_response(response, OutputFormat.JSON)
renderable = self._version_basic_response(response, format=OutputFormat.JSON, legacy_format=legacy_format)
self.app.render(renderable, format=OutputFormat.JSON.value)

@ex(
Expand Down
17 changes: 17 additions & 0 deletions esper/controllers/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@ class DeviceState(BaseEnum):
POLICY_APPLICATION_IN_PROGRESS = 50

INACTIVE = 60
WIPE_IN_PROGRESS = 70

ONBOARDING_IN_PROGRESS = 80
ONBOARDING_FAILED = 90
ONBOARDED = 100

AFW_ACCOUNT_ADDED = 110
APPS_INSTALLED = 120
BRANDING_PROCESSED = 130
PERMISSION_POLICY_PROCESSED = 140
DEVICE_POLICY_PROCESSED = 150
DEVICE_SETTINGS_PROCESSED = 160
SECURITY_POLICY_PROCESSED = 170
PHONE_POLICY_PROCESSED = 180
CUSTOM_SETTINGS_PROCESSED = 190

REGISTERED=200


class OutputFormat(BaseEnum):
Expand Down
2 changes: 1 addition & 1 deletion esper/core/version.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from cement.utils.version import get_version as cement_get_version

VERSION = (0, 0, 13, 'final', 0)
VERSION = (0, 0, 16, 'final', 0)


def get_version(version=VERSION):
Expand Down
8 changes: 4 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ cement==3.0.2
clint==0.5.1
colorlog==4.0.2
crayons==0.2.0
esperclient==0.1.2
jinja2==2.11.3
esperclient==0.1.3
jinja2==3.1.6

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls validate that version upgrades of these libraries not breaking

pyyaml==6.0.1
requests==2.32.0
tabulate==0.8.3
tinydb==3.13.0
tqdm==4.32.1
tqdm==4.66.3
markupsafe==2.0.1
cryptography==42.0.8
cryptography==44.0.1

# For Secure ADB
pyOpenSSL==24.1.0
Loading
Loading