textpy


Nametextpy JSON
Version 0.1.31 PyPI version JSON
download
home_pagehttps://github.com/Chitaoji/textpy/
SummaryReads a python module and statically analyzes it.
upload_time2024-11-29 03:37:36
maintainerNone
docs_urlNone
authorChitaoji
requires_python>=3.8.13
licenseBSD
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            
# textpy
Reads a python module and statically analyzes it. This works well with jupyter extensions in *VS Code*, and will have better performance when the module files are formatted with *PEP-8*.

## Installation
```sh
$ pip install textpy
```

## Requirements
```txt
lazyr>=0.0.16
hintwith>=0.1.3
typing-extensions
black
colorama
```
**NOTE:** *pandas*>=1.4.0 is recommended but not necessary.

## Quick Start
To demonstrate the usage of this module, we put a file named `myfile.py` under `./examples/` (you can find it in the repository, or create a new file of your own):
```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from typing import Optional


class MyBook:
    """
    A book that records a story.

    Parameters
    ----------
    story : str, optional
        Story to record, by default None.

    """

    def __init__(self, story: Optional[str] = None) -> None:
        if story is None:
            self.content = "This book is empty."
        self.content = story


def print_my_book(book: MyBook) -> None:
    """
    Print a book.

    Parameters
    ----------
    book : MyBook
        A book.

    """
    print(book.content)
```
Run the following codes to find all the occurrences of some pattern (for example, "MyBook") in `myfile.py`:
```py
>>> import textpy as tx
>>> myfile = tx.module("./examples/myfile.py") # reads the python module

>>> myfile.findall("MyBook")
examples/myfile.py:7: 'class <MyBook>:'
examples/myfile.py:24: 'def print_my_book(book: <MyBook>) -> None:'
examples/myfile.py:30: '    book : <MyBook>'
```
If you are using a jupyter notebook, you can run a cell like this:
```py
>>> myfile.findall("content")
```
<!--html-->
<table id="T_19b39">
  <thead>
    <tr>
      <th id="T_19b39_level0_col0" class="col_heading level0 col0" >source</th>
      <th id="T_19b39_level0_col1" class="col_heading level0 col1" >match</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td id="T_19b39_row0_col0" class="data row0 col0" ><a href='examples/myfile.py#L7' style='text-decoration:none;color:inherit'>myfile</a>.<a href='examples/myfile.py#L7' style='text-decoration:none;color:inherit'>MyBook</a>:<a href='examples/myfile.py#L7' style='text-decoration:none;color:inherit'>7</a></td>
      <td id="T_19b39_row0_col1" class="data row0 col1" >class <a href='examples/myfile.py#L7' style='text-decoration:none;color:#cccccc;background-color:#505050'>MyBook</a>:</td>
    </tr>
    <tr>
      <td id="T_19b39_row1_col0" class="data row1 col0" ><a href='examples/myfile.py#L24' style='text-decoration:none;color:inherit'>myfile</a>.<a href='examples/myfile.py#L24' style='text-decoration:none;color:inherit'>print_my_book()</a>:<a href='examples/myfile.py#L24' style='text-decoration:none;color:inherit'>24</a></td>
      <td id="T_19b39_row1_col1" class="data row1 col1" >def print_my_book(book: <a href='examples/myfile.py#L24' style='text-decoration:none;color:#cccccc;background-color:#505050'>MyBook</a>) -> None:</td>
    </tr>
    <tr>
      <td id="T_19b39_row2_col0" class="data row2 col0" ><a href='examples/myfile.py#L30' style='text-decoration:none;color:inherit'>myfile</a>.<a href='examples/myfile.py#L30' style='text-decoration:none;color:inherit'>print_my_book()</a>:<a href='examples/myfile.py#L30' style='text-decoration:none;color:inherit'>30</a></td>
      <td id="T_19b39_row2_col1" class="data row2 col1" >    book : <a href='examples/myfile.py#L30' style='text-decoration:none;color:#cccccc;background-color:#505050'>MyBook</a></td>
    </tr>
  </tbody>
</table>
<!--/html-->

Note that in the jupyter notebook case, the matched substrings are **clickable**, linking to where the patterns were found.

## Examples
### tx.module()
The previous demonstration introduced the core function `tx.module()`. The return value of `tx.module()` is a subinstance of the abstract class `tx.TextTree`, which supports various text manipulation methods:
```py
>>> isinstance(myfile, tx.TextTree)
True
```
Sometimes, your python module may contain not just one file, but don't worry, since `tx.module()` provides support for complex file hierarchies. If the path points to a single file, the return type will be `PyFile`; otherwise, the return type will be `PyDir` - both of which are subclasses of `tx.TextTree`.

In conclusion, once you've got a python package, you can simply give the package dirpath to `tx.module()`, and do things like before:

```py
>>> pkg_dir = "" # type any path here
>>> pattern = "" # type any regex pattern here

>>> res = tx.module(pkg_dir).findall(pattern)
```

### tx.TextTree.findall()
As mentioned before, user can use `.findall()` to find all non-overlapping matches of some pattern in a python module.
```py
>>> myfile.findall("optional")
examples/myfile.py:13: '    story : str, <optional>'
```
The object returned by `.findall()` has a `_repr_mimebundle_()` method to beautify the representation inside a jupyter notebook. However, you can compulsively disable this feature by setting `display_params.use_mimebundle` to False:
```py
>>> from textpy import display_params
>>> display_params.use_mimebundle = False
``` 
In addition, the `.findall()` method has some optional parameters to customize the pattern, including `whole_word=`, `case_sensitive=`, and `regex=`.
```py
>>> myfile.findall("mybook", case_sensitive=False, regex=False, whole_word=True)
examples/myfile.py:7: 'class <MyBook>:'
examples/myfile.py:24: 'def print_my_book(book: <MyBook>) -> None:'
examples/myfile.py:30: '    book : <MyBook>'
```

### tx.TextTree.replace()
Use `.replace()` to find all non-overlapping matches of some pattern, and replace them with another string:
```py
>>> replacer = myfile.replace("book", "magazine")
>>> replacer
examples/myfile.py:9: '    A <book/magazine> that records a story.'
examples/myfile.py:20: '            self.content = "This <book/magazine> is empty."'
examples/myfile.py:24: 'def print_my_<book/magazine>(<book/magazine>: MyBook) -> None:'
examples/myfile.py:26: '    Print a <book/magazine>.'
examples/myfile.py:30: '    <book/magazine> : MyBook'
examples/myfile.py:31: '        A <book/magazine>.'
examples/myfile.py:34: '    print(<book/magazine>.content)'
```
At this point, the replacement has not actually taken effect yet. Use `.confirm()` to confirm the changes and write them to the file(s):
```py
>>> replacer.confirm()
{'successful': ['examples/myfile.py'], 'failed': []}
```
If you want to rollback the changes, run:
```py
>>> replacer.rollback()
{'successful': ['examples/myfile.py'], 'failed': []}
```

### tx.TextTree.delete()
Use `.delete()` to find all non-overlapping matches of some pattern, and delete them:
```py
>>> deleter = myfile.delete("book")
>>> deleter
examples/myfile.py:9: '    A <book> that records a story.'
examples/myfile.py:20: '            self.content = "This <book> is empty."'
examples/myfile.py:24: 'def print_my_<book>(<book>: MyBook) -> None:'
examples/myfile.py:26: '    Print a <book>.'
examples/myfile.py:30: '    <book> : MyBook'
examples/myfile.py:31: '        A <book>.'
examples/myfile.py:34: '    print(<book>.content)'

>>> deleter.confirm()
{'successful': ['examples/myfile.py'], 'failed': []}

>>> deleter.rollback()
{'successful': ['examples/myfile.py'], 'failed': []}
```

## See Also
### Github repository
* https://github.com/Chitaoji/textpy/

### PyPI project
* https://pypi.org/project/textpy/

## License
This project falls under the BSD 3-Clause License.

## History
### v0.1.31
* Got ANSI escapes to work on Windows.

### v0.1.30
* New optional paramter `include=` for `module()`.
* Renamed `tx.PyText` to `tx.TextTree`; the name `PyText` will be deprecated.

### v0.1.29
* Updated `PyText.check_format()`, which now returns a boolean value instead of None.
* Updated the `ignore=` parameter for `module()`, which now accepts a list of path-patterns. Paths matching any of these patterns will be ignored when searching for files.

### v0.1.28
* Fixed issue: failed to display special characters in `*._repr_mimebundle_()`.

### v0.1.27
* New gloabal parameters: `tree_style=`, `table_style=`, `use_mimebundle=`, and `skip_line_numbers=` - find them under `tx.display_params`.
* Defined `display_params.defaults()` for users to get the default values of the parameters.
* New subclass `PyProperty` inherited from `PyMethod`. Class properties will be stored in instances of `PyProperty` instead of `PyMethod` in the future.
* Updated the method `PyText.jumpto()`: it now allows "/" as delimiters (in addition to "."); if a class or callable is defined more than once, jump to the last (previously first) place where it was defined. 
* `PyText` has a `_repr_mimebundle_()` method now.
* New property `PyText.imports`.
* Created a utility class `HTMLTableMaker` in place of `Styler`; this significantly reduces the running overhead of `*._repr_mimebundle_()`.

### v0.1.26
* Updated `utils.re_extensions`: 
  * bugfix for `rsplit()`;
  * new string operation `quote_collapse()`.

### v0.1.25
* Updated `utils.re_extensions`: 
  * **Important:** we've decided to extract `utils.re_extensions` into an independent package named `re_extensions` (presently at v0.0.3), so any future updates should be looked up in https://github.com/Chitaoji/re-extensions instead; we will stay in sync with it, however;
  * `real_findall()` now returns match objects instead of spans and groups;
  * `smart_sub()` accepts a new optional parameter called `count=`;
  * `SmartPattern` supports [] to indicate a Unicode (str) or bytes pattern (like what `re.Pattern` does);
  * new regex operations `smart_split()`, `smart_findall()`, `line_findall()`, `smart_subn()`, and `smart_fullmatch()`;
  * created a namespace `Smart` for all the smart operations;
  * bugfixes for `rsplit()`, `lsplit()`, and `smart_sub()`.
* Reduced the running cost of `PyText.findall()` by taking advantage of the new regex operation `line_findall()`.

### v0.1.24
* New methods `PyText.is_file()` and `PyText.is_dir()` to find out whether the instance represents a file / directory.
* New method `PyText.check_format()` for format checking.
* Defined the comparison ordering methods `__eq__()`, `__gt__()`, and `__ge__()` for `PyText`. They compares two `PyText` object via their absolute paths.
* Updated `utils.re_extensions`: 
  * new regex operations `smart_search()`, `smart_match()`, and `smart_sub()`;
  * new string operation `counted_strip()`;
  * new utility classes `SmartPattern` and `SmartMatch`.
  * new utility functions `find_right_bracket()` and `find_left_bracket()`.

### v0.1.23
* New string operation `utils.re_extensions.word_wrap()`.
* Various improvements.

### v0.1.22
* The module-level function `textpy()` is going to be deprecated to avoid conflicts with the package name `textpy`. Please use `module()` insead.
* New methods `PyText.replace()` and `PyText.delete()`.
* New class `Replacer` as the return type of `PyText.replace()`, with public methods `.confirm()`, `.rollback()`, etc.
* Added a dunder method `PyText.__truediv__()` as an alternative to `PyText.jumpto()`.
* New subclass `PyContent` inherited from `PyText`. A `PyContent` object stores a part of a file that is not storable by instances of other subclasses.

### v0.1.21
* Improved behavior of clickables.

### v0.1.20
* Fixed issue: incorrect file links in the output of `TextPy.findall()`;

### v0.1.19
* Various improvements.

### v0.1.18
* Updated LICENSE.

### v0.1.17
* Refactored README.md.

### v0.1.16
* Lazily imported *pandas* to reduce the time cost for importing.

### v0.1.12
* New optional parameters for `TextPy.findall()` :
  * `whole_word=` : whether to match whole words only;
  * `case_sensitive=` : specifies case sensitivity.

### v0.1.10
* New optional parameter `encoding=` for `textpy()`.

### v0.1.9
* Removed unnecessary dependencies.

### v0.1.8
* Bugfix under Windows system.

### v0.1.5
* Provided compatibility with *pandas* versions lower than 1.4.0.
* Updated `textpy()` :
  * `Path` object is now acceptable as the positional argument;
  * new optional parameter `home=` for specifying the home path.
* More flexible presentation of output from `TextPy.findall()`.

### v0.1.4
* Fixed a display issue of README.md on PyPI.

### v0.1.3
* Initial release.


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Chitaoji/textpy/",
    "name": "textpy",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8.13",
    "maintainer_email": null,
    "keywords": null,
    "author": "Chitaoji",
    "author_email": "2360742040@qq.com",
    "download_url": null,
    "platform": null,
    "description": "\n# textpy\nReads a python module and statically analyzes it. This works well with jupyter extensions in *VS Code*, and will have better performance when the module files are formatted with *PEP-8*.\n\n## Installation\n```sh\n$ pip install textpy\n```\n\n## Requirements\n```txt\nlazyr>=0.0.16\nhintwith>=0.1.3\ntyping-extensions\nblack\ncolorama\n```\n**NOTE:** *pandas*>=1.4.0 is recommended but not necessary.\n\n## Quick Start\nTo demonstrate the usage of this module, we put a file named `myfile.py` under `./examples/` (you can find it in the repository, or create a new file of your own):\n```py\n#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\nfrom typing import Optional\n\n\nclass MyBook:\n    \"\"\"\n    A book that records a story.\n\n    Parameters\n    ----------\n    story : str, optional\n        Story to record, by default None.\n\n    \"\"\"\n\n    def __init__(self, story: Optional[str] = None) -> None:\n        if story is None:\n            self.content = \"This book is empty.\"\n        self.content = story\n\n\ndef print_my_book(book: MyBook) -> None:\n    \"\"\"\n    Print a book.\n\n    Parameters\n    ----------\n    book : MyBook\n        A book.\n\n    \"\"\"\n    print(book.content)\n```\nRun the following codes to find all the occurrences of some pattern (for example, \"MyBook\") in `myfile.py`:\n```py\n>>> import textpy as tx\n>>> myfile = tx.module(\"./examples/myfile.py\") # reads the python module\n\n>>> myfile.findall(\"MyBook\")\nexamples/myfile.py:7: 'class <MyBook>:'\nexamples/myfile.py:24: 'def print_my_book(book: <MyBook>) -> None:'\nexamples/myfile.py:30: '    book : <MyBook>'\n```\nIf you are using a jupyter notebook, you can run a cell like this:\n```py\n>>> myfile.findall(\"content\")\n```\n<!--html-->\n<table id=\"T_19b39\">\n  <thead>\n    <tr>\n      <th id=\"T_19b39_level0_col0\" class=\"col_heading level0 col0\" >source</th>\n      <th id=\"T_19b39_level0_col1\" class=\"col_heading level0 col1\" >match</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td id=\"T_19b39_row0_col0\" class=\"data row0 col0\" ><a href='examples/myfile.py#L7' style='text-decoration:none;color:inherit'>myfile</a>.<a href='examples/myfile.py#L7' style='text-decoration:none;color:inherit'>MyBook</a>:<a href='examples/myfile.py#L7' style='text-decoration:none;color:inherit'>7</a></td>\n      <td id=\"T_19b39_row0_col1\" class=\"data row0 col1\" >class <a href='examples/myfile.py#L7' style='text-decoration:none;color:#cccccc;background-color:#505050'>MyBook</a>:</td>\n    </tr>\n    <tr>\n      <td id=\"T_19b39_row1_col0\" class=\"data row1 col0\" ><a href='examples/myfile.py#L24' style='text-decoration:none;color:inherit'>myfile</a>.<a href='examples/myfile.py#L24' style='text-decoration:none;color:inherit'>print_my_book()</a>:<a href='examples/myfile.py#L24' style='text-decoration:none;color:inherit'>24</a></td>\n      <td id=\"T_19b39_row1_col1\" class=\"data row1 col1\" >def print_my_book(book: <a href='examples/myfile.py#L24' style='text-decoration:none;color:#cccccc;background-color:#505050'>MyBook</a>) -> None:</td>\n    </tr>\n    <tr>\n      <td id=\"T_19b39_row2_col0\" class=\"data row2 col0\" ><a href='examples/myfile.py#L30' style='text-decoration:none;color:inherit'>myfile</a>.<a href='examples/myfile.py#L30' style='text-decoration:none;color:inherit'>print_my_book()</a>:<a href='examples/myfile.py#L30' style='text-decoration:none;color:inherit'>30</a></td>\n      <td id=\"T_19b39_row2_col1\" class=\"data row2 col1\" >    book : <a href='examples/myfile.py#L30' style='text-decoration:none;color:#cccccc;background-color:#505050'>MyBook</a></td>\n    </tr>\n  </tbody>\n</table>\n<!--/html-->\n\nNote that in the jupyter notebook case, the matched substrings are **clickable**, linking to where the patterns were found.\n\n## Examples\n### tx.module()\nThe previous demonstration introduced the core function `tx.module()`. The return value of `tx.module()` is a subinstance of the abstract class `tx.TextTree`, which supports various text manipulation methods:\n```py\n>>> isinstance(myfile, tx.TextTree)\nTrue\n```\nSometimes, your python module may contain not just one file, but don't worry, since `tx.module()` provides support for complex file hierarchies. If the path points to a single file, the return type will be `PyFile`; otherwise, the return type will be `PyDir` - both of which are subclasses of `tx.TextTree`.\n\nIn conclusion, once you've got a python package, you can simply give the package dirpath to `tx.module()`, and do things like before:\n\n```py\n>>> pkg_dir = \"\" # type any path here\n>>> pattern = \"\" # type any regex pattern here\n\n>>> res = tx.module(pkg_dir).findall(pattern)\n```\n\n### tx.TextTree.findall()\nAs mentioned before, user can use `.findall()` to find all non-overlapping matches of some pattern in a python module.\n```py\n>>> myfile.findall(\"optional\")\nexamples/myfile.py:13: '    story : str, <optional>'\n```\nThe object returned by `.findall()` has a `_repr_mimebundle_()` method to beautify the representation inside a jupyter notebook. However, you can compulsively disable this feature by setting `display_params.use_mimebundle` to False:\n```py\n>>> from textpy import display_params\n>>> display_params.use_mimebundle = False\n``` \nIn addition, the `.findall()` method has some optional parameters to customize the pattern, including `whole_word=`, `case_sensitive=`, and `regex=`.\n```py\n>>> myfile.findall(\"mybook\", case_sensitive=False, regex=False, whole_word=True)\nexamples/myfile.py:7: 'class <MyBook>:'\nexamples/myfile.py:24: 'def print_my_book(book: <MyBook>) -> None:'\nexamples/myfile.py:30: '    book : <MyBook>'\n```\n\n### tx.TextTree.replace()\nUse `.replace()` to find all non-overlapping matches of some pattern, and replace them with another string:\n```py\n>>> replacer = myfile.replace(\"book\", \"magazine\")\n>>> replacer\nexamples/myfile.py:9: '    A <book/magazine> that records a story.'\nexamples/myfile.py:20: '            self.content = \"This <book/magazine> is empty.\"'\nexamples/myfile.py:24: 'def print_my_<book/magazine>(<book/magazine>: MyBook) -> None:'\nexamples/myfile.py:26: '    Print a <book/magazine>.'\nexamples/myfile.py:30: '    <book/magazine> : MyBook'\nexamples/myfile.py:31: '        A <book/magazine>.'\nexamples/myfile.py:34: '    print(<book/magazine>.content)'\n```\nAt this point, the replacement has not actually taken effect yet. Use `.confirm()` to confirm the changes and write them to the file(s):\n```py\n>>> replacer.confirm()\n{'successful': ['examples/myfile.py'], 'failed': []}\n```\nIf you want to rollback the changes, run:\n```py\n>>> replacer.rollback()\n{'successful': ['examples/myfile.py'], 'failed': []}\n```\n\n### tx.TextTree.delete()\nUse `.delete()` to find all non-overlapping matches of some pattern, and delete them:\n```py\n>>> deleter = myfile.delete(\"book\")\n>>> deleter\nexamples/myfile.py:9: '    A <book> that records a story.'\nexamples/myfile.py:20: '            self.content = \"This <book> is empty.\"'\nexamples/myfile.py:24: 'def print_my_<book>(<book>: MyBook) -> None:'\nexamples/myfile.py:26: '    Print a <book>.'\nexamples/myfile.py:30: '    <book> : MyBook'\nexamples/myfile.py:31: '        A <book>.'\nexamples/myfile.py:34: '    print(<book>.content)'\n\n>>> deleter.confirm()\n{'successful': ['examples/myfile.py'], 'failed': []}\n\n>>> deleter.rollback()\n{'successful': ['examples/myfile.py'], 'failed': []}\n```\n\n## See Also\n### Github repository\n* https://github.com/Chitaoji/textpy/\n\n### PyPI project\n* https://pypi.org/project/textpy/\n\n## License\nThis project falls under the BSD 3-Clause License.\n\n## History\n### v0.1.31\n* Got ANSI escapes to work on Windows.\n\n### v0.1.30\n* New optional paramter `include=` for `module()`.\n* Renamed `tx.PyText` to `tx.TextTree`; the name `PyText` will be deprecated.\n\n### v0.1.29\n* Updated `PyText.check_format()`, which now returns a boolean value instead of None.\n* Updated the `ignore=` parameter for `module()`, which now accepts a list of path-patterns. Paths matching any of these patterns will be ignored when searching for files.\n\n### v0.1.28\n* Fixed issue: failed to display special characters in `*._repr_mimebundle_()`.\n\n### v0.1.27\n* New gloabal parameters: `tree_style=`, `table_style=`, `use_mimebundle=`, and `skip_line_numbers=` - find them under `tx.display_params`.\n* Defined `display_params.defaults()` for users to get the default values of the parameters.\n* New subclass `PyProperty` inherited from `PyMethod`. Class properties will be stored in instances of `PyProperty` instead of `PyMethod` in the future.\n* Updated the method `PyText.jumpto()`: it now allows \"/\" as delimiters (in addition to \".\"); if a class or callable is defined more than once, jump to the last (previously first) place where it was defined. \n* `PyText` has a `_repr_mimebundle_()` method now.\n* New property `PyText.imports`.\n* Created a utility class `HTMLTableMaker` in place of `Styler`; this significantly reduces the running overhead of `*._repr_mimebundle_()`.\n\n### v0.1.26\n* Updated `utils.re_extensions`: \n  * bugfix for `rsplit()`;\n  * new string operation `quote_collapse()`.\n\n### v0.1.25\n* Updated `utils.re_extensions`: \n  * **Important:** we've decided to extract `utils.re_extensions` into an independent package named `re_extensions` (presently at v0.0.3), so any future updates should be looked up in https://github.com/Chitaoji/re-extensions instead; we will stay in sync with it, however;\n  * `real_findall()` now returns match objects instead of spans and groups;\n  * `smart_sub()` accepts a new optional parameter called `count=`;\n  * `SmartPattern` supports [] to indicate a Unicode (str) or bytes pattern (like what `re.Pattern` does);\n  * new regex operations `smart_split()`, `smart_findall()`, `line_findall()`, `smart_subn()`, and `smart_fullmatch()`;\n  * created a namespace `Smart` for all the smart operations;\n  * bugfixes for `rsplit()`, `lsplit()`, and `smart_sub()`.\n* Reduced the running cost of `PyText.findall()` by taking advantage of the new regex operation `line_findall()`.\n\n### v0.1.24\n* New methods `PyText.is_file()` and `PyText.is_dir()` to find out whether the instance represents a file / directory.\n* New method `PyText.check_format()` for format checking.\n* Defined the comparison ordering methods `__eq__()`, `__gt__()`, and `__ge__()` for `PyText`. They compares two `PyText` object via their absolute paths.\n* Updated `utils.re_extensions`: \n  * new regex operations `smart_search()`, `smart_match()`, and `smart_sub()`;\n  * new string operation `counted_strip()`;\n  * new utility classes `SmartPattern` and `SmartMatch`.\n  * new utility functions `find_right_bracket()` and `find_left_bracket()`.\n\n### v0.1.23\n* New string operation `utils.re_extensions.word_wrap()`.\n* Various improvements.\n\n### v0.1.22\n* The module-level function `textpy()` is going to be deprecated to avoid conflicts with the package name `textpy`. Please use `module()` insead.\n* New methods `PyText.replace()` and `PyText.delete()`.\n* New class `Replacer` as the return type of `PyText.replace()`, with public methods `.confirm()`, `.rollback()`, etc.\n* Added a dunder method `PyText.__truediv__()` as an alternative to `PyText.jumpto()`.\n* New subclass `PyContent` inherited from `PyText`. A `PyContent` object stores a part of a file that is not storable by instances of other subclasses.\n\n### v0.1.21\n* Improved behavior of clickables.\n\n### v0.1.20\n* Fixed issue: incorrect file links in the output of `TextPy.findall()`;\n\n### v0.1.19\n* Various improvements.\n\n### v0.1.18\n* Updated LICENSE.\n\n### v0.1.17\n* Refactored README.md.\n\n### v0.1.16\n* Lazily imported *pandas* to reduce the time cost for importing.\n\n### v0.1.12\n* New optional parameters for `TextPy.findall()` :\n  * `whole_word=` : whether to match whole words only;\n  * `case_sensitive=` : specifies case sensitivity.\n\n### v0.1.10\n* New optional parameter `encoding=` for `textpy()`.\n\n### v0.1.9\n* Removed unnecessary dependencies.\n\n### v0.1.8\n* Bugfix under Windows system.\n\n### v0.1.5\n* Provided compatibility with *pandas* versions lower than 1.4.0.\n* Updated `textpy()` :\n  * `Path` object is now acceptable as the positional argument;\n  * new optional parameter `home=` for specifying the home path.\n* More flexible presentation of output from `TextPy.findall()`.\n\n### v0.1.4\n* Fixed a display issue of README.md on PyPI.\n\n### v0.1.3\n* Initial release.\n\n",
    "bugtrack_url": null,
    "license": "BSD",
    "summary": "Reads a python module and statically analyzes it.",
    "version": "0.1.31",
    "project_urls": {
        "Homepage": "https://github.com/Chitaoji/textpy/"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7f9189910bbeb48265c5cce71fd61e161a2ba5e0d23d04e2c2eb7eb48289d029",
                "md5": "7eedcab574211fee76ef860040968e04",
                "sha256": "6c294a81b30daee02357223fd05d70ca83277f21cd19ca94124eba0acc674bc6"
            },
            "downloads": -1,
            "filename": "textpy-0.1.31-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7eedcab574211fee76ef860040968e04",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": ">=3.8.13",
            "size": 35867,
            "upload_time": "2024-11-29T03:37:36",
            "upload_time_iso_8601": "2024-11-29T03:37:36.300248Z",
            "url": "https://files.pythonhosted.org/packages/7f/91/89910bbeb48265c5cce71fd61e161a2ba5e0d23d04e2c2eb7eb48289d029/textpy-0.1.31-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-29 03:37:36",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Chitaoji",
    "github_project": "textpy",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "textpy"
}
        
Elapsed time: 0.77046s