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

improve command line interface #84

Open
wants to merge 5 commits into
base: b-1.1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion examples/describe_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from wlts import WLTS

# Specify the URL of the WLTS instance to be used
service = WLTS('https://brazildatacube.dpi.inpe.br/wlts/')
service = WLTS('https://data.inpe.br/bdc/wlts/v1')

# Get collection metadata
print(service['prodes_amazonia_legal'])
2 changes: 1 addition & 1 deletion examples/list_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

# You should create a wlts object attached to a given service
# Specify the URL of the WLTS instance to be used
service = WLTS('https://brazildatacube.dpi.inpe.br/wlts/')
service = WLTS('https://data.inpe.br/bdc/wlts/v1/')

# Returns the list of collections available on the service
print(service.collections)
2 changes: 1 addition & 1 deletion examples/text-repr.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from wlts import *

service = WLTS('https://brazildatacube.dpi.inpe.br/wlts/')
service = WLTS('https://data.inpe.br/bdc/wlts/v1/')

print(service)
print(str(service))
Expand Down
3 changes: 2 additions & 1 deletion examples/trajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from wlts import WLTS

# Specify the URL of the WLTS instance to be used
service = WLTS(url='https://brazildatacube.dpi.inpe.br/wlts/', access_token='change-me')
service = WLTS(url='https://data.inpe.br/bdc/wlts/v1/')

# Example of trajectory operation
# Make sure the collection is available in service
Expand All @@ -31,6 +31,7 @@
collections='prodes_amazonia_legal,mapbiomas-v8',
start_date='2010'
)
print (tj_m)
for tj in tj_m['trajectories']:
print(tj.trajectory)

Expand Down
2 changes: 1 addition & 1 deletion run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
pydocstyle wlts examples tests setup.py && \
isort wlts examples tests setup.py --check-only --diff && \
check-manifest --ignore ".drone.yml,.readthedocs.yml" && \
sphinx-build -qnW --color -b doctest docs/sphinx/ docs/sphinx/_build/doctest && \
sphinx-build -qn --color -b doctest docs/sphinx/ docs/sphinx/_build/doctest && \
pytest
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
'pandas>=1.1',
'geopandas>=0.8.2',
'plotly==5.5.0',
'rich>=13.9.2',
'lccs @ git+https://github.com/brazil-data-cube/[email protected]',
]

Expand Down
2 changes: 1 addition & 1 deletion tests/test_trajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def test_trajectory(self, wlts_objects, requests_mock, runner, config_obj):
], obj=config_obj)

assert result.exit_code == 0
assert 'trajectory:' in result.output
assert 'Processing trajectory request...' in result.output


if __name__ == '__main__':
Expand Down
100 changes: 75 additions & 25 deletions wlts/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
#

"""Command line interface for the WLTS client."""
from time import time

import click
from rich.console import Console
from rich.progress import BarColumn, Progress, TextColumn, TimeElapsedColumn
from rich.syntax import Syntax
from rich.table import Table

from .wlts import WLTS

Expand All @@ -35,9 +40,12 @@ def __init__(self):

pass_config = click.make_pass_decorator(Config, ensure=True)

console = Console()



@click.group()
@click.option('--url', type=click.STRING, default='https://brazildatacube.dpi.inpe.br/wlts/',
@click.option('--url', type=click.STRING, default='https://data.inpe.br/bdc/wlts/v1/',
help='The WLTS server address (an URL).')
@click.option('--lccs-url', type=click.STRING, default='https://brazildatacube.dpi.inpe.br/lccs',
help='The LCCS-WS address (an URL).')
Expand All @@ -56,17 +64,21 @@ def cli(config, url, lccs_url, access_token):
def list_collections(config: Config, verbose):
"""Return the list of available collections in the service provider."""
if verbose:
click.secho(f'Server: {config.url}', bold=True, fg='black')
click.secho('\tRetrieving the list of available coverages... ',
bold=False, fg='black')
console.print(f'[bold black]Server: [green]{config.url}[/green]', style="bold")
console.print('[black]\tRetrieving the list of available coverages...[/black]')

table = Table(title="Available Collections", show_header=True, header_style="bold magenta")
table.add_column("Collection Name", style="green", no_wrap=True)

for collection in config.service.collections:
click.secho(f'\t\t- {collection}', bold=True, fg='green')
table.add_row(collection)

click.secho('\tFinished!', bold=False, fg='black')
console.print(table)
console.print('[black]\tFinished![/black]')

else:
for cv in config.service.collections:
click.secho(f'{cv}', bold=True, fg='green')
for collection in config.service.collections:
console.print(f'[green]{collection}[/green]', style="bold")


@cli.command()
Expand All @@ -75,18 +87,25 @@ def list_collections(config: Config, verbose):
help='The collection name')
@pass_config
def describe(config: Config, verbose, collection):
"""Retrieve the coverage metadata."""
"""Retrieve the collection metadata."""
import json
if verbose:
click.secho(f'Server: {config.url}', bold=True, fg='black')
click.secho('\tRetrieving the collection metadata... ',
bold=False, fg='black')
console.print(f'[bold black]Server: [green]{config.url}[/green]', style="bold")
console.print('[black]\tRetrieving the collection metadata...[/black]')

# Retrieve the collection metadata
cv = config.service[collection]

click.secho(f'\t- {cv}', bold=True, fg='green')
# Convert the metadata to a formatted JSON string
formatted_json = json.dumps(cv, indent=4,ensure_ascii=False)

# Use Syntax from rich to display JSON nicely formatted
syntax = Syntax(formatted_json, "json", theme="monokai", line_numbers=True)
console.print(f'\t[green bold]- Collection Metadata:[/green bold]')
console.print(syntax) # Pretty formatted JSON with syntax highlighting

if verbose:
click.secho('\tFinished!', bold=False, fg='black')
console.print('[black]\tFinished![/black]')


@cli.command()
Expand All @@ -111,12 +130,11 @@ def describe(config: Config, verbose, collection):
def trajectory(config: Config, verbose, collections, start_date, end_date, latitude, longitude, language):
"""Return the trajectory associated to the location."""
if verbose:
click.secho(f'Server: {config.url}', bold=True, fg='black')
click.secho('\tRetrieving trajectory... ',
bold=False, fg='black')
console.print(f"[bold black]Server: [green]{config.url}[/green]")
console.print('[black]\tRetrieving trajectory...[/black]')

# Prepare query parameters
args = dict()

if collections:
args["collections"] = collections
if start_date:
Expand All @@ -126,13 +144,45 @@ def trajectory(config: Config, verbose, collections, start_date, end_date, latit
if language:
args["language"] = language

retval = config.service.tj(
latitude=latitude,
longitude=longitude,
**args
)
# Progress bar to indicate processing time
with Progress(
TextColumn("[progress.description]{task.description}"),
BarColumn(),
TimeElapsedColumn(),
) as progress:
task = progress.add_task("[cyan]Processing trajectory request...", total=100)

# Measure start time
start_time = time()

# Simulate progress
for _ in range(5):
progress.update(task, advance=20)

# Retrieve trajectory data
retval = config.service.tj(latitude=latitude, longitude=longitude, **args)

# Measure end time
end_time = time()

# Calculate total time
total_time = end_time - start_time

# Display the trajectory data in a table format
table = Table(title=f"Trajectory Results (Time: {total_time:.2f} seconds)")

# Add table columns
table.add_column("Class", style="cyan", no_wrap=True)
table.add_column("Collection", style="magenta")
table.add_column("Date", justify="right", style="green")
table.add_column("Point ID", justify="right", style="yellow")

# Add rows from the trajectory data
for entry in retval.trajectory:
table.add_row(entry['class'], entry['collection'], entry['date'], str(entry['point_id']))

click.secho(f'\ttrajectory: {retval.trajectory}')
# Display the table
console.print(table)

if verbose:
click.secho('\tFinished!', bold=False, fg='black')
console.print(f'[black]\tFinished in {total_time:.2f} seconds![/black]')
48 changes: 22 additions & 26 deletions wlts/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,86 +16,82 @@
# along with this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
#
"""A class that represents a Collection in WLTS."""
from typing import Any, Dict, Union

from .utils import Utils


class Collections(dict):
"""A class that describes a collection in WLTS.

.. note::
For more information about collection definition, please, refer to
`WLTS specification <https://github.com/brazil-data-cube/wlts-spec>`_.
For more information about collection definition, refer to
`WLTS specification <https://github.com/brazil-data-cube/wlts-spec>`_.
"""

def __init__(self, service, metadata=None):
def __init__(self, service: Any, metadata: Dict[str, Any] = None) -> None:
"""Create a collection object associated to a WLTS client.

Args:
service (wlts.WLTS): The client to be used by the collection object.
metadata (dict): The collection metadata.
metadata (Dict[str, Any]): The collection metadata.
"""
#: WLTS: The associated WLTS client to be used by the collection object.
self._service = service

super(Collections, self).__init__(metadata or {})
super().__init__(metadata or {})

@property
def collection_type(self):
def collection_type(self) -> str:
"""Return the type of the collection."""
return self['collection_type']

@property
def description(self):
def description(self) -> str:
"""Return the description of the collection."""
return self['description']

@property
def detail(self):
def detail(self) -> str:
"""Return the detail of the collection."""
return self['detail']

@property
def name(self):
def name(self) -> str:
"""Return the name of the collection."""
return self['name']

@property
def title(self):
def title(self) -> str:
"""Return the title of the collection."""
return self['title']

@property
def period(self):
def period(self) -> Union[str, None]:
"""Return the period of the collection."""
return self['period']
return self.get('period')

@property
def temporal_resolution(self):
def temporal_resolution(self) -> str:
"""Return the temporal resolution of the collection."""
return self['temporal_resolution']

@property
def spatial_extent(self):
def spatial_extent(self) -> Dict[str, Any]:
"""Return the spatial extent of the collection."""
return self['spatial_extent']

@property
def classification_system(self):
def classification_system(self) -> Dict[str, Any]:
"""Return the classification system of the collection."""
return self['classification_system']

def __str__(self):
def __str__(self) -> str:
"""Return the string representation of the Collection object."""
return super().__str__()

def __repr__(self):
def __repr__(self) -> str:
"""Return the Collection object representation."""
wlts_repr = repr(self._service)
return f'Collection(service={wlts_repr}, metadata={super().__repr__()})'

text = f'Collection(service={wlts_repr}, metadata={super().__repr__()}'

return text

def _repr_html_(self):
"""HTML repr."""
def _repr_html_(self) -> str:
"""HTML representation for IPython rich display."""
return Utils.render_html('collection.html', collection=self)
34 changes: 19 additions & 15 deletions wlts/templates/collection.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,35 @@
<b>Unit:</b> {{collection.temporal_resolution['unit']}}
<b>Value:</b> {{collection.temporal_resolution['value']}}
</div>
</br>
<br>
<b>Classification System:</b>
<div>
<b>Id:</b> {{collection.classification_system['id']}}
<b>Title:</b> {{collection.classification_system['title']}}
<b>Name:</b> {{collection.classification_system['name']}}
<b>Version:</b> {{collection.classification_system['version']}}
</div>
</br>
<br>
<div>
<b>Extent</b>
</div>
<div>
<table>
<tr>
<th>max_x</th>
<th>min_x</th>
<th>max_y</th>
<th>min_y</th>
</tr>
<tr>
<td>{{collection.spatial_extent['xmax']}}</td>
<td>{{collection.spatial_extent['xmin']}}</td>
<td>{{collection.spatial_extent['ymax']}}</td>
<td>{{collection.spatial_extent['ymin']}}</td>
</tr>
<table class="table table-striped">
<thead>
<tr>
<th>max_x</th>
<th>min_x</th>
<th>max_y</th>
<th>min_y</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{collection.spatial_extent['xmax']}}</td>
<td>{{collection.spatial_extent['xmin']}}</td>
<td>{{collection.spatial_extent['ymax']}}</td>
<td>{{collection.spatial_extent['ymin']}}</td>
</tr>
</tbody>
</table>
</div>
Loading