diff --git a/docs/index.rst b/docs/index.rst index 952a9e982..42e0bf453 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -58,6 +58,7 @@ Example above creates Neptune `experiment Experiment Notebook + Utils .. toctree:: :maxdepth: 1 diff --git a/docs/technical_reference/utils.rst b/docs/technical_reference/utils.rst new file mode 100644 index 000000000..fc3e619b2 --- /dev/null +++ b/docs/technical_reference/utils.rst @@ -0,0 +1,10 @@ +Utils +===== + +.. automodule:: neptune.git_info + :members: + :show-inheritance: + +.. automodule:: neptune.utils + :members: + :show-inheritance: diff --git a/neptune/__init__.py b/neptune/__init__.py index fbd1e90d2..e36c46cc7 100644 --- a/neptune/__init__.py +++ b/neptune/__init__.py @@ -198,32 +198,98 @@ def append_tags(tag, *tags): def remove_tag(tag): + """Removes single tag from experiment. + + Alias for: :meth:`~neptune.experiments.Experiment.remove_tag` + """ get_experiment().remove_tag(tag) def set_property(key, value): + """Set `key-value` pair as an experiment property. + + If property with given ``key`` does not exist, it adds a new one. + + Alias for: :meth:`~neptune.experiments.Experiment.set_property` + """ get_experiment().set_property(key, value) def remove_property(key): + """Removes a property with given key. + + Alias for: :meth:`~neptune.experiments.Experiment.remove_property` + """ get_experiment().remove_property(key) def send_metric(channel_name, x, y=None, timestamp=None): + """Log metrics (numeric values) in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_metric` + """ return get_experiment().send_metric(channel_name, x, y, timestamp) +def log_metric(log_name, x, y=None, timestamp=None): + """Log metrics (numeric values) in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_metric` + """ + return get_experiment().log_metric(log_name, x, y, timestamp) + + def send_text(channel_name, x, y=None, timestamp=None): + """Log text data in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_text` + """ return get_experiment().send_text(channel_name, x, y, timestamp) +def log_text(log_name, x, y=None, timestamp=None): + """Log text data in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_text` + """ + return get_experiment().send_text(log_name, x, y, timestamp) + + def send_image(channel_name, x, y=None, name=None, description=None, timestamp=None): + """Log image data in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_image` + """ return get_experiment().send_image(channel_name, x, y, name, description, timestamp) +def log_image(log_name, x, y=None, name=None, description=None, timestamp=None): + """Log image data in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_image` + """ + return get_experiment().send_image(log_name, x, y, name, description, timestamp) + + def send_artifact(artifact): + """Save an artifact (file) in experiment storage. + + Alias for :meth:`~neptune.experiments.Experiment.log_artifact` + """ + return get_experiment().send_artifact(artifact) + + +def log_artifact(artifact): + """Save an artifact (file) in experiment storage. + + Alias for :meth:`~neptune.experiments.Experiment.log_artifact` + """ return get_experiment().send_artifact(artifact) def stop(traceback=None): + """Marks experiment as finished (succeeded or failed). + + Alias for :meth:`~neptune.experiments.Experiment.stop` + """ get_experiment().stop(traceback) diff --git a/neptune/experiments.py b/neptune/experiments.py index 8960fa112..f29d6e675 100644 --- a/neptune/experiments.py +++ b/neptune/experiments.py @@ -320,7 +320,9 @@ def upload_source_files(self, source_files): experiment=self) def send_metric(self, channel_name, x, y=None, timestamp=None): - """Alias for :meth:`~neptune.experiments.Experiment.log_metric` + """Log metrics (numeric values) in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_metric` """ return self.log_metric(channel_name, x, y, timestamp) @@ -375,7 +377,9 @@ def log_metric(self, log_name, x, y=None, timestamp=None): self._channels_values_sender.send(log_name, ChannelType.NUMERIC.value, value) def send_text(self, channel_name, x, y=None, timestamp=None): - """Alias for :meth:`~neptune.experiments.Experiment.log_text` + """Log text data in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_text` """ return self.log_text(channel_name, x, y, timestamp) @@ -425,7 +429,9 @@ def log_text(self, log_name, x, y=None, timestamp=None): self._channels_values_sender.send(log_name, ChannelType.TEXT.value, value) def send_image(self, channel_name, x, y=None, name=None, description=None, timestamp=None): - """Alias for :meth:`~neptune.experiments.Experiment.log_image` + """Log image data in Neptune. + + Alias for :meth:`~neptune.experiments.Experiment.log_image` """ return self.log_image(channel_name, x, y, name, description, timestamp) @@ -477,14 +483,28 @@ def log_image(self, log_name, x, y=None, image_name=None, description=None, time self._channels_values_sender.send(log_name, ChannelType.IMAGE.value, value) def send_artifact(self, artifact): - """Alias for :meth:`~neptune.experiments.Experiment.log_artifact` + """Save an artifact (file) in experiment storage. + + Alias for :meth:`~neptune.experiments.Experiment.log_artifact` """ return self.log_artifact(artifact) def log_artifact(self, artifact): - """ + """Save an artifact (file) in experiment storage. + + Args: + artifact (:obj:`str`): A path to the file in local filesystem. + Raises: `StorageLimitReached`: When storage limit in the project has been reached. + + Example: + Assuming that `experiment` is an instance of :class:`~neptune.experiments.Experiment`: + + .. code:: python3 + + # simple use + experiment.log_artifact('images/wrong_prediction_1.png') """ if not os.path.exists(artifact): raise FileNotFound(artifact) @@ -626,6 +646,23 @@ def get_properties(self): return dict((p.key, p.value) for p in experiment.properties) def set_property(self, key, value): + """Set `key-value` pair as an experiment property. + + If property with given ``key`` does not exist, it adds a new one. + + Args: + key (:obj:`str`): Property key. + value (:obj:`obj`): New value of a property. + + Examples: + Assuming that `experiment` is an instance of :class:`~neptune.experiments.Experiment`: + + .. code:: python3 + + experiment.set_property('model', 'LightGBM') + experiment.set_property('magic-number', 7) + + """ properties = {p.key: p.value for p in self._client.get_experiment(self.internal_id).properties} properties[key] = value return self._client.update_experiment( @@ -634,6 +671,20 @@ def set_property(self, key, value): ) def remove_property(self, key): + """Removes a property with given key. + + Args: + key (single :obj:`str`): + Key of property to remove. + + Examples: + Assuming that `experiment` is an instance of :class:`~neptune.experiments.Experiment`: + + .. code:: python3 + + experiment.remove_property('host') + + """ properties = {p.key: p.value for p in self._client.get_experiment(self.internal_id).properties} del properties[key] return self._client.update_experiment( @@ -782,6 +833,26 @@ def start(self, ) def stop(self, exc_tb=None): + """Marks experiment as finished (succeeded or failed). + + Args: + exc_tb (:obj:`str`, optional, default is ``None``): Additional traceback information + to be stored in experiment details in case of failure (stacktrace, etc). + If this argument is ``None`` the experiment will be marked as succeeded. + Otherwise, experiment will be marked as failed. + + Examples: + Assuming that `experiment` is an instance of :class:`~neptune.experiments.Experiment`: + + .. code:: python3 + + # Marks experiment as succeeded + experiment.stop() + + # Assuming 'ex' is some exception, + # it marks experiment as failed with exception info in experiment details. + experiment.stop(str(ex)) + """ self._channels_values_sender.join() diff --git a/neptune/git_info.py b/neptune/git_info.py index 7ac499ec9..8674582da 100644 --- a/neptune/git_info.py +++ b/neptune/git_info.py @@ -16,7 +16,21 @@ class GitInfo(object): - """ Holds information about a git repository""" + """Class that keeps information about a git repository in experiment. + + When :meth:`~neptune.projects.Project.create_experiment` is invoked, instance of this class is created to + store information about git repository. + This information is later presented in the experiment details tab in the Neptune web application. + + Args: + commit_id (:obj:`str`): commit id sha. + message (:obj:`str`, optional, default is ``""``): commit message. + author_name (:obj:`str`, optional, default is ``""``): commit author username. + author_email (:obj:`str`, optional, default is ``""``): commit author email. + commit_date (:obj:`datetime.datetime`, optional, default is ``""``): commit datetime. + repository_dirty (:obj:`bool`, optional, default is ``True``): + ``True``, if the repository has uncommitted changes, ``False`` otherwise. + """ def __init__(self, commit_id, message="", @@ -24,16 +38,6 @@ def __init__(self, author_email="", commit_date="", repository_dirty=True): - """Creates a new instance of a git repository info - - Args: - commit_id(str): commit id sha - message(str): commit message - author_name(str): commit author username - author_email(str): commit author email - commit_date(datetime.datetime): commit datetime - repository_dirty(bool): True, if the repository has uncommitted changes - """ if commit_id is None: raise TypeError("commit_id must not be None") diff --git a/neptune/projects.py b/neptune/projects.py index f93fa6300..846579836 100644 --- a/neptune/projects.py +++ b/neptune/projects.py @@ -294,6 +294,19 @@ def create_experiment(self, * If set to ``False`` and uncaught exception occurs, then no action is performed in the Web application. As a consequence, experiment's status is `running` or `not responding`. + git_info (:class:`~neptune.git_info.GitInfo`, optional, default is ``None``): + + | Instance of the class :class:`~neptune.git_info.GitInfo` that provides information about + the git repository from which experiment was started. + | If ``None`` is passed, + system attempts to automatically extract information about git repository in the following way: + + * System looks for `.git` file in the current directory and, if not found, + goes up recursively until `.git` file will be found + (see: :meth:`~neptune.utils.get_git_info`). + * If there is no git repository, + then no information about git is displayed in experiment details in Neptune web application. + hostname (:obj:`str`, optional, default is ``None``): If ``None``, neptune automatically get `hostname` information. User can also set `hostname` directly by passing :obj:`str`. diff --git a/neptune/utils.py b/neptune/utils.py index a459aa669..9ebcf089d 100644 --- a/neptune/utils.py +++ b/neptune/utils.py @@ -115,11 +115,6 @@ def _split_df_by_stems(df): def discover_git_repo_location(): - """ Attempts to retrieve git repository location. - - Returns: - string: path, that should be the best candidate to find git repository, or None - """ import __main__ if hasattr(__main__, '__file__'): @@ -128,29 +123,29 @@ def discover_git_repo_location(): def get_git_info(repo_path=None): - """ Attempts to retrieve git info from repository. + """Retrieve information about git repository. - In case of failure, None will be returned + If attempt fails, ``None`` will be returned. Args: - repo_path(str): an optional path to the repository, from which to extract information. - Passing None will resolve the same repository as calling git.Repo(): + repo_path (:obj:`str`, optional, default is ``None``): + + | Path to the repository from which extract information about git. + | If ``None`` is passed, calling ``get_git_info`` is equivalent to calling + ``git.Repo(search_parent_directories=True)``. + Check `GitPython `_ + docs for more information. Returns: - neptune.GitInfo: An object representing information about chosen git repository + :class:`~neptune.git_info.GitInfo` - An object representing information about git repository. Examples: - Get git info from current directory - >>> from neptune.utils import get_git_info - >>> git_info = get_git_info('.') + .. code:: python3 - Create an experiment with git history + # Get git info from the current directory + git_info = get_git_info('.') - >>> from neptune.sessions import Session - >>> session = Session() - >>> project = session.get_projects('neptune-ml')['neptune-ml/Salt-Detection'] - >>> experiment = project.create_experiment(git_info=git_info) """ try: import git