{"id":17384546,"url":"https://github.com/pgdr/purses","last_synced_at":"2025-10-08T17:05:27.732Z","repository":{"id":139058575,"uuid":"137942315","full_name":"pgdr/purses","owner":"pgdr","description":null,"archived":false,"fork":false,"pushed_at":"2020-12-15T11:33:43.000Z","size":79,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-01T23:42:06.322Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pgdr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-06-19T20:29:46.000Z","updated_at":"2020-12-15T11:33:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"0ee00d17-3f4f-4d4d-b999-789feb5153d7","html_url":"https://github.com/pgdr/purses","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgdr%2Fpurses","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgdr%2Fpurses/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgdr%2Fpurses/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pgdr%2Fpurses/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pgdr","download_url":"https://codeload.github.com/pgdr/purses/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245924501,"owners_count":20694731,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-16T07:45:50.040Z","updated_at":"2025-10-08T17:05:22.696Z","avatar_url":"https://github.com/pgdr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Purses\n\nPurses is a Pandas Curses program.\n\nIt allows you to jump into a curses view of any dataframe and edit the contents,\nas well as open a Pandas dataframe from the command line with the purses command\nline tool.\n\n## Installation\n\nEither run\n\n* `pip install purses`\n* `pip install git+https://github.com/pgdr/purses`\n* or clone this repository to unlock new loot boxes\n\n## Starting Purses\n\nPurses can be used either as a terminal tool by running `purses myfile.csv`, or\nfrom inside a Python shell.\n\n```python\nimport purses\npurses.load('myfile.csv')\n```\n\nYou can also load a dataframe directly\n\n```python\nimport purses\nimport pandas as pd\ndf = pd.read_csv('myfile.csv')\npurses.load(df)\n```\n\n## Usage\n\nNavigation in Purses is done via the `\u003cUP\u003e`/`\u003cDOWN\u003e`/`\u003cRIGHT\u003e`/`\u003cLEFT\u003e` keys.\n\nQuit Purses with `q`.\n\n\n\n## Defining your own key bindings\n\nAny sufficiently advanced tool supports programmatic tools bindings.\n\nAny key press event can trigger a callback with the provided signature below,\nhowever, it is advisable to add also `*args` and `**kwargs` to the function\nparameter list to accomodate for future additions.\n\n```python\nfunction(model, nav, io)\n```\n\nIf a key (e.g. `s`) is bound to the above `function`, everytime `s` is pressed,\n`function` is called, with `model` containing accessors to the dataframe in\nquestion.\n\nThe `nav` object has functions, `up`, `down`, `left`, `right`, for moving the\ncursor.  It also has a function `to(row, col)` to move to a specific cell.\n`nav` also holds `row` and `col` the coordinates to the cursor's cell.\n\nThe `io` object has a function `message` which can be given any string to\ndisplay in the message area and `user_input` is used to get a string from the\nuser.\n\n\n### Some examples\n\n\n\n```python\n\nclass summer:\n    def __init__(self):\n        self.sum_ = 0\n    def add(self, model, nav, io, *args, **kwargs):\n        self.sum_ += model.get()  # the coordinates are optional\n        io.message('Current sum: {}'.format(self.sum_))\n    def flush(self, model, nav, io, *args, **kwargs):\n        model.set(self.sum_)\n        io.message('Flushed: {}'.format(self.sum_))\n        self.sum_ = 0\n\nautumn = summer()\npurses.load(df, bindings={'s': autumn.add, 'f': autumn.flush})\n```\n\n\nTo _square_ the element of a cell, we can hook the key `2` to the squaring\nfunction:\n\n```python\n@purses.binding('2')\ndef square(self, model, *args, **kwargs):\n    model.set(model.get()**2)\n```\n\nIndeed, when using decorators to bind the key to a function, there is no reason\nto hang on to the name, so the above could be implemented as\n```python\n@purses.binding('2')\ndef _(self, model, *args, **kwargs):\n    model.set(model.get()**2)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgdr%2Fpurses","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpgdr%2Fpurses","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpgdr%2Fpurses/lists"}