gophermap 0.0.1__tar.gz → 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.4
2
+ Name: gophermap
3
+ Version: 0.0.2
4
+ Summary: A simple library for parsng Gophermaps
5
+ Keywords: Gopher,Gophermap,Hypertext,library,Markup,parser,Small Web,smolweb
6
+ Author: Dave Pearson
7
+ Author-email: Dave Pearson <davep@davep.org>
8
+ License-Expression: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python :: 3 :: Only
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Typing :: Typed
18
+ Requires-Python: >=3.12
19
+ Project-URL: Homepage, https://gophermap.davep.dev/
20
+ Project-URL: Repository, https://github.com/davep/gophermap
21
+ Project-URL: Documentation, https://gophermap.davep.dev/
22
+ Project-URL: Source, https://github.com/davep/gophermap
23
+ Project-URL: Issues, https://github.com/davep/gophermap/issues
24
+ Project-URL: Discussions, https://github.com/davep/gophermap/discussions
25
+ Description-Content-Type: text/markdown
26
+
27
+ # gophermap - A simple library for parsing Gopher maps
28
+
29
+ `gophermap` is a small and simple library that provides code for parsing
30
+ Gopher responses.
31
+
32
+ ## Installation
33
+
34
+ `gophermap` is [available from pypi](https://pypi.org/project/gophermap/)
35
+ and can be installed with your package installer of choice.
36
+
37
+ With `pip`:
38
+
39
+ ```shell
40
+ pip install gophermap
41
+ ```
42
+
43
+ With `uv`:
44
+
45
+ ```shell
46
+ uv add gophermap
47
+ ```
48
+
49
+ [//]: # (README.md ends here)
@@ -0,0 +1,23 @@
1
+ # gophermap - A simple library for parsing Gopher maps
2
+
3
+ `gophermap` is a small and simple library that provides code for parsing
4
+ Gopher responses.
5
+
6
+ ## Installation
7
+
8
+ `gophermap` is [available from pypi](https://pypi.org/project/gophermap/)
9
+ and can be installed with your package installer of choice.
10
+
11
+ With `pip`:
12
+
13
+ ```shell
14
+ pip install gophermap
15
+ ```
16
+
17
+ With `uv`:
18
+
19
+ ```shell
20
+ uv add gophermap
21
+ ```
22
+
23
+ [//]: # (README.md ends here)
@@ -0,0 +1,111 @@
1
+ [project]
2
+ name = "gophermap"
3
+ version = "0.0.2"
4
+ description = "A simple library for parsng Gophermaps"
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Dave Pearson", email = "davep@davep.org" }
8
+ ]
9
+ requires-python = ">=3.12"
10
+ dependencies = []
11
+ license = "MIT"
12
+ keywords = [
13
+ "Gopher",
14
+ "Gophermap",
15
+ "Hypertext",
16
+ "library",
17
+ "Markup",
18
+ "parser",
19
+ "Small Web",
20
+ "smolweb",
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 3 - Alpha",
24
+ "Operating System :: OS Independent",
25
+ "Programming Language :: Python :: 3 :: Only",
26
+ "Programming Language :: Python :: 3",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Programming Language :: Python :: 3.13",
29
+ "Programming Language :: Python :: 3.14",
30
+ "Topic :: Software Development :: Libraries",
31
+ "Typing :: Typed",
32
+ ]
33
+
34
+ [project.urls]
35
+ Homepage = "https://gophermap.davep.dev/"
36
+ Repository = "https://github.com/davep/gophermap"
37
+ Documentation = "https://gophermap.davep.dev/"
38
+ Source = "https://github.com/davep/gophermap"
39
+ Issues = "https://github.com/davep/gophermap/issues"
40
+ Discussions = "https://github.com/davep/gophermap/discussions"
41
+
42
+ [project.scripts]
43
+ gophermap = "gophermap.__main__:parse_input"
44
+
45
+ [build-system]
46
+ requires = ["uv_build>=0.11.32,<0.12.0"]
47
+ build-backend = "uv_build"
48
+
49
+ [[tool.uv.index]]
50
+ name = "testpypi"
51
+ url = "https://test.pypi.org/simple/"
52
+ publish-url = "https://test.pypi.org/legacy/"
53
+ explicit = true
54
+
55
+ [tool.pyright]
56
+ venvPath="."
57
+ venv=".venv"
58
+ exclude=[".venv"]
59
+
60
+ [dependency-groups]
61
+ dev = [
62
+ "codespell>=2.4.3",
63
+ "mypy>=2.3.0",
64
+ "pre-commit>=4.6.0",
65
+ "ruff>=0.15.22",
66
+ ]
67
+ docs = [
68
+ "mkdocs>=1.6.1,<2",
69
+ "mkdocs-material>=9.7.6",
70
+ "mkdocstrings[python]>=1.0.4",
71
+ ]
72
+ test = [
73
+ "pytest>=9.1.1",
74
+ "pytest-cov>=7.1.0",
75
+ ]
76
+
77
+ [tool.ruff.lint]
78
+ select = [
79
+ # pycodestyle
80
+ "E",
81
+ # Pyflakes
82
+ "F",
83
+ # pyupgrade
84
+ "UP",
85
+ # flake8-bugbear
86
+ "B",
87
+ # flake8-simplify
88
+ "SIM",
89
+ # isort
90
+ "I",
91
+ ]
92
+
93
+ [tool.ruff.lint.pycodestyle]
94
+ max-line-length = 120
95
+
96
+ [tool.coverage.run]
97
+ omit = [
98
+ "tests/*"
99
+ ]
100
+
101
+ [tool.coverage.report]
102
+ exclude_lines = [
103
+ "pragma: no cover",
104
+ "def __repr__",
105
+ "raise AssertionError",
106
+ "raise NotImplementedError",
107
+ "if __name__ == .__main__.:",
108
+ "if TYPE_CHECKING:",
109
+ "class .*\\bProtocol\\):",
110
+ "@(abc\\.)?abstractmethod",
111
+ ]
@@ -0,0 +1,34 @@
1
+ """Provides tools for working with Gopher maps."""
2
+
3
+ ##############################################################################
4
+ # Python imports.
5
+ from importlib.metadata import version
6
+
7
+ ######################################################################
8
+ # Main library information.
9
+ __author__ = "Dave Pearson"
10
+ __copyright__ = "Copyright 2026, Dave Pearson"
11
+ __credits__ = ["Dave Pearson"]
12
+ __maintainer__ = "Dave Pearson"
13
+ __email__ = "davep@davep.org"
14
+ __version__: str = version("gophermap")
15
+ __licence__ = "MIT"
16
+
17
+ ##############################################################################
18
+ # Local imports.
19
+ from .exceptions import GopherMapError, NoFields
20
+ from .gopher_map import GopherMap
21
+ from .item import GopherItem
22
+ from .item_type import ItemType
23
+
24
+ ##############################################################################
25
+ # Exports.
26
+ __all__ = [
27
+ "GopherItem",
28
+ "GopherMap",
29
+ "GopherMapError",
30
+ "ItemType",
31
+ "NoFields",
32
+ ]
33
+
34
+ ### __init__.py ends here
@@ -0,0 +1,25 @@
1
+ """A simple parser to show how the library works."""
2
+
3
+ ##############################################################################
4
+ # Python imports.
5
+ import fileinput
6
+
7
+ ##############################################################################
8
+ # Local imports.
9
+ from gophermap import GopherMap
10
+
11
+
12
+ ##############################################################################
13
+ def parse_input() -> None:
14
+ """Parse the input from stdin or files and print the parsed Gopher map."""
15
+ with fileinput.input() as gopher_map:
16
+ for gopher_item in GopherMap("".join(gopher_map)).items:
17
+ print(f"{gopher_item!r}")
18
+
19
+
20
+ ##############################################################################
21
+ if __name__ == "__main__":
22
+ parse_input()
23
+
24
+
25
+ ### __main__.py ends here
@@ -0,0 +1,14 @@
1
+ """Exceptions for the library."""
2
+
3
+
4
+ ##############################################################################
5
+ class GopherMapError(Exception):
6
+ """Base exception for all errors raised by the GopherMap library."""
7
+
8
+
9
+ ##############################################################################
10
+ class NoFields(GopherMapError):
11
+ """Raised when a Gopher item has no fields."""
12
+
13
+
14
+ ### exceptions.py ends here
@@ -0,0 +1,57 @@
1
+ """Provides a class for parsing and holding a Gopher map."""
2
+
3
+ ##############################################################################
4
+ # Python imports.
5
+ from collections.abc import Iterator
6
+ from functools import cached_property
7
+ from typing import Final
8
+
9
+ ##############################################################################
10
+ # Local imports.
11
+ from .item import GopherItem
12
+
13
+ ##############################################################################
14
+ EOF: Final = ".\r\n"
15
+ """The EOF marker for a Gopher map."""
16
+
17
+
18
+ ##############################################################################
19
+ class GopherMap:
20
+ """A class for parsing and holding a Gopher map."""
21
+
22
+ def __init__(self, map_text: str) -> None:
23
+ """Initialise the Gopher map.
24
+
25
+ Args:
26
+ map_text: The text of the Gopher map.
27
+ """
28
+ self._raw = map_text
29
+ """The raw text of the Gopher map."""
30
+
31
+ @staticmethod
32
+ def _parse_map(map_text: str) -> Iterator[GopherItem]:
33
+ """Parse the Gopher map text into a list of Gopher items.
34
+
35
+ Args:
36
+ map_text: The text of the Gopher map.
37
+
38
+ Yields:
39
+ Gopher items.
40
+ """
41
+ for line in map_text.splitlines(keepends=True):
42
+ if line == EOF:
43
+ break
44
+ yield GopherItem(line)
45
+
46
+ @property
47
+ def raw(self) -> str:
48
+ """The raw text of the Gopher map."""
49
+ return self._raw
50
+
51
+ @cached_property
52
+ def items(self) -> tuple[GopherItem, ...]:
53
+ """The list of Gopher items in the map."""
54
+ return tuple(self._parse_map(self._raw))
55
+
56
+
57
+ ### gopher_map.py ends here
@@ -0,0 +1,75 @@
1
+ """Provides a class for holding an item in the Gopher map."""
2
+
3
+ ##############################################################################
4
+ # Local imports.
5
+ from .exceptions import NoFields
6
+ from .item_type import ItemType
7
+
8
+
9
+ ##############################################################################
10
+ class GopherItem:
11
+ """A class for holding an item in the Gopher map."""
12
+
13
+ def __init__(self, line: str) -> None:
14
+ """Initialise the Gopher item.
15
+
16
+ Args:
17
+ line: The line of text from the Gopher map.
18
+ """
19
+ if not line:
20
+ raise NoFields("The Gopher item line is empty.")
21
+ if "\t" not in line:
22
+ raise NoFields(f"The Gopher item line has no tab characters: {line!r}")
23
+ self._raw = line
24
+ """The raw text of the Gopher item."""
25
+ fields = line.rstrip("\r\n").split("\t")
26
+ self._type = ItemType(fields[0][0] or ItemType.INFO)
27
+ """The type of the Gopher item."""
28
+ self._display_text = fields[0][1:] if len(fields) > 0 else ""
29
+ """The display text of the Gopher item."""
30
+ self._selector = fields[1] if len(fields) > 1 else ""
31
+ """The selector of the Gopher item."""
32
+ self._host = fields[2] if len(fields) > 2 else ""
33
+ """The host of the Gopher item."""
34
+ self._port = int(fields[3]) if len(fields) > 3 and fields[3].isdigit() else 70
35
+ """The port of the Gopher item."""
36
+
37
+ @property
38
+ def raw(self) -> str:
39
+ """The raw text of the Gopher item."""
40
+ return self._raw
41
+
42
+ @property
43
+ def type(self) -> ItemType:
44
+ """The type of the Gopher item."""
45
+ return self._type
46
+
47
+ @property
48
+ def display_text(self) -> str:
49
+ """The display text of the Gopher item."""
50
+ return self._display_text
51
+
52
+ @property
53
+ def selector(self) -> str:
54
+ """The selector of the Gopher item."""
55
+ return self._selector
56
+
57
+ @property
58
+ def host(self) -> str:
59
+ """The host of the Gopher item."""
60
+ return self._host
61
+
62
+ @property
63
+ def port(self) -> int:
64
+ """The port of the Gopher item."""
65
+ return self._port
66
+
67
+ def __repr__(self) -> str:
68
+ """Return a string representation of the Gopher item."""
69
+ return (
70
+ f"GopherItem(type={self.type!r}, display_text={self.display_text!r}, "
71
+ f"selector={self.selector!r}, host={self.host!r}, port={self.port!r})"
72
+ )
73
+
74
+
75
+ ### item.py ends here
@@ -0,0 +1,69 @@
1
+ """Provides an enumeration for the different types of Gopher items."""
2
+
3
+ ##############################################################################
4
+ # Future imports.
5
+ from __future__ import annotations
6
+
7
+ ##############################################################################
8
+ # Python imports.
9
+ from enum import StrEnum
10
+
11
+
12
+ ##############################################################################
13
+ class ItemType(StrEnum):
14
+ """An enumeration for the different types of Gopher items."""
15
+
16
+ TEXT = "0"
17
+ """A text file."""
18
+ MENU = "1"
19
+ """A menu."""
20
+ CSO = "2"
21
+ """A CSO phone book."""
22
+ ERROR = "3"
23
+ """An error message."""
24
+ BINHEX = "4"
25
+ """A BinHexed file."""
26
+ DOS_FILE = "5"
27
+ """A DOS file."""
28
+ UUENCODED = "6"
29
+ """A uuencoded file."""
30
+ INDEX_SEARCH = "7"
31
+ """An index search."""
32
+ TELNET = "8"
33
+ """A telnet session."""
34
+ BINARY = "9"
35
+ """A binary file."""
36
+ INFO = "i"
37
+ """An informational message."""
38
+ GIF = "g"
39
+ """A GIF image."""
40
+ IMAGE = "I"
41
+ """An image file."""
42
+ HTML = "h"
43
+ """An HTML file."""
44
+ DOCUMENT = "d"
45
+ """A document file."""
46
+ AUDIO = "s"
47
+ """An audio file."""
48
+ PDF = "P"
49
+ """A PDF file."""
50
+ XML = "X"
51
+ """An XML file."""
52
+ UNKNOWN = "unknown"
53
+ """An unknown type."""
54
+
55
+ @classmethod
56
+ def _missing_(cls, value: object) -> ItemType:
57
+ """Handle missing values in the enumeration.
58
+
59
+ Args:
60
+ value: The value that is missing.
61
+
62
+ Returns:
63
+ The corresponding ItemType for the missing value.
64
+ """
65
+ assert isinstance(value, str)
66
+ return ItemType.UNKNOWN
67
+
68
+
69
+ ### item_type.py ends here
gophermap-0.0.1/PKG-INFO DELETED
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: gophermap
3
- Version: 0.0.1
4
- Summary: Coming soon
5
- Author: Dave Pearson
6
- Author-email: Dave Pearson <davep@davep.org>
7
- Requires-Python: >=3.12
8
- Description-Content-Type: text/markdown
9
-
gophermap-0.0.1/README.md DELETED
File without changes
@@ -1,23 +0,0 @@
1
- [project]
2
- name = "gophermap"
3
- version = "0.0.1"
4
- description = "Coming soon"
5
- readme = "README.md"
6
- authors = [
7
- { name = "Dave Pearson", email = "davep@davep.org" }
8
- ]
9
- requires-python = ">=3.12"
10
- dependencies = []
11
-
12
- [project.scripts]
13
- gophermap = "gophermap:main"
14
-
15
- [build-system]
16
- requires = ["uv_build>=0.11.32,<0.12.0"]
17
- build-backend = "uv_build"
18
-
19
- [[tool.uv.index]]
20
- name = "testpypi"
21
- url = "https://test.pypi.org/simple/"
22
- publish-url = "https://test.pypi.org/legacy/"
23
- explicit = true
@@ -1,2 +0,0 @@
1
- def main() -> None:
2
- print("Hello from gophermap!")