ciffer 0.1.0__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.
Files changed (37) hide show
  1. ciffer-0.1.0/.github/workflows/lint.yml +19 -0
  2. ciffer-0.1.0/.github/workflows/publish.yml +20 -0
  3. ciffer-0.1.0/.github/workflows/test.yml +21 -0
  4. ciffer-0.1.0/.gitignore +7 -0
  5. ciffer-0.1.0/.pre-commit-config.yaml +29 -0
  6. ciffer-0.1.0/.python-version +1 -0
  7. ciffer-0.1.0/LICENSE +21 -0
  8. ciffer-0.1.0/PKG-INFO +180 -0
  9. ciffer-0.1.0/README.md +156 -0
  10. ciffer-0.1.0/pyproject.toml +61 -0
  11. ciffer-0.1.0/src/ciffer/__init__.py +21 -0
  12. ciffer-0.1.0/src/ciffer/cif/__init__.py +333 -0
  13. ciffer-0.1.0/src/ciffer/cif/altloc.py +79 -0
  14. ciffer-0.1.0/src/ciffer/cif/assembly.py +121 -0
  15. ciffer-0.1.0/src/ciffer/cif/bonds.py +275 -0
  16. ciffer-0.1.0/src/ciffer/cif/category.py +151 -0
  17. ciffer-0.1.0/src/ciffer/cif/hierarchy.py +415 -0
  18. ciffer-0.1.0/src/ciffer/cif/metadata.py +166 -0
  19. ciffer-0.1.0/src/ciffer/cif/pdb.py +77 -0
  20. ciffer-0.1.0/src/ciffer/cif/rcsb.py +28 -0
  21. ciffer-0.1.0/src/ciffer/cif/writable.py +315 -0
  22. ciffer-0.1.0/src/ciffer/py.typed +0 -0
  23. ciffer-0.1.0/src/ciffer/serialize.py +100 -0
  24. ciffer-0.1.0/src/ciffer/structure.py +340 -0
  25. ciffer-0.1.0/src/ciffer/table.py +337 -0
  26. ciffer-0.1.0/src/ciffer/view.py +374 -0
  27. ciffer-0.1.0/tests/data/1EJG.cif.gz +0 -0
  28. ciffer-0.1.0/tests/data/1G2J.cif.gz +0 -0
  29. ciffer-0.1.0/tests/data/1L2Y_3models.cif.gz +0 -0
  30. ciffer-0.1.0/tests/data/1M4X.cif.gz +0 -0
  31. ciffer-0.1.0/tests/data/1STP.cif.gz +0 -0
  32. ciffer-0.1.0/tests/data/1STP.pdb.gz +0 -0
  33. ciffer-0.1.0/tests/data/4DWA.cif.gz +0 -0
  34. ciffer-0.1.0/tests/test_cif.py +758 -0
  35. ciffer-0.1.0/tests/test_structure.py +256 -0
  36. ciffer-0.1.0/tests/test_table.py +90 -0
  37. ciffer-0.1.0/uv.lock +580 -0
@@ -0,0 +1,19 @@
1
+ name: Lint
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ jobs:
9
+ lint:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+ - uses: astral-sh/setup-uv@v5
14
+ with:
15
+ enable-cache: true
16
+ - run: uv sync --locked
17
+ - run: uv run ruff check
18
+ - run: uv run ruff format --check
19
+ - run: uv run ty check
@@ -0,0 +1,20 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ environment: pypi
11
+ permissions:
12
+ contents: read
13
+ id-token: write # PyPI trusted publishing
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v5
17
+ - run: uv sync --locked
18
+ - run: uv run pytest
19
+ - run: uv build
20
+ - run: uv publish
@@ -0,0 +1,21 @@
1
+ name: Test
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [main]
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python: ["3.11", "3.12", "3.13", "3.14"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: astral-sh/setup-uv@v5
17
+ with:
18
+ enable-cache: true
19
+ python-version: ${{ matrix.python }}
20
+ - run: uv sync --locked
21
+ - run: uv run pytest
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.py[oc]
3
+ build/
4
+ dist/
5
+ wheels/
6
+ *.egg-info
7
+ .venv
@@ -0,0 +1,29 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ - id: check-toml
9
+
10
+ - repo: local
11
+ hooks:
12
+ - id: ruff-check
13
+ name: ruff check
14
+ entry: uv run --no-sync ruff check --fix
15
+ language: system
16
+ types_or: [python, pyi]
17
+ require_serial: true
18
+ - id: ruff-format
19
+ name: ruff format
20
+ entry: uv run --no-sync ruff format
21
+ language: system
22
+ types_or: [python, pyi, markdown]
23
+ require_serial: true
24
+ - id: ty
25
+ name: ty check
26
+ entry: uv run --no-sync ty check
27
+ language: system
28
+ types_or: [python, pyi]
29
+ pass_filenames: false
@@ -0,0 +1 @@
1
+ 3.11
ciffer-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Howon Lee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ciffer-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.5
2
+ Name: ciffer
3
+ Version: 0.1.0
4
+ Summary: Biomolecular structures as NumPy tables, ready for ML pipelines.
5
+ Project-URL: Repository, https://github.com/Buddha7771/ciffer
6
+ Project-URL: Issues, https://github.com/Buddha7771/ciffer/issues
7
+ Author-email: Howon Lee <hwlee7771@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: machine-learning,mmcif,numpy,pdb,protein,structure
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: gemmi>=0.7.5
21
+ Requires-Dist: numpy>=2.2
22
+ Requires-Dist: zstandard>=0.25.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ # ciffer
26
+
27
+ [![PyPI](https://img.shields.io/pypi/v/ciffer)](https://pypi.org/project/ciffer/) [![Tests](https://github.com/Buddha7771/ciffer/actions/workflows/test.yml/badge.svg)](https://github.com/Buddha7771/ciffer/actions/workflows/test.yml)
28
+
29
+ Biomolecular structures as NumPy tables, ready for ML pipelines.
30
+
31
+ Every structure is three linked tables (atoms, residues, and chains) whose columns are NumPy arrays. Built on [gemmi](https://github.com/project-gemmi/gemmi).
32
+
33
+ - **Read and write in one line.** mmCIF and PDB, with models, altlocs, and assemblies chosen as you read.
34
+ - **Navigate like PyMOL.** Select atoms, hop to their residues and chains, and extract what you keep.
35
+ - **Handle columns like pandas.** Every column is a NumPy array, and your own columns go in with `[]`.
36
+ - **Save once, load as is.** `to_bytes()` keeps every column, bond, and metadata entry.
37
+
38
+ ## Installation
39
+
40
+ ```sh
41
+ pip install ciffer
42
+ ```
43
+
44
+ ciffer needs Python 3.11 or newer.
45
+
46
+ ## Usage
47
+
48
+ ### A first look
49
+
50
+ ```python
51
+ import ciffer
52
+
53
+ st = ciffer.fetch("1stp", assembly=True) # from RCSB, as the biological tetramer
54
+
55
+ st.atoms.name[:4] # ['N', 'CA', 'C', 'O']
56
+ st.atoms.xyz.shape # (4004, 3)
57
+ len(st.atoms.bond) # 3280
58
+
59
+ st.residues.name[:4] # ['ASP', 'PRO', 'SER', 'LYS']
60
+ st.residues.label_seq_id[:4] # [1, 2, 3, 4]
61
+
62
+ st.chains.label_asym_id[:3] # ['A1', 'B1', 'C1']
63
+ st.chains.entity_type[:3] # ['polymer', 'non-polymer', 'water']
64
+
65
+ st.metadata["resolution"] # 2.6
66
+ st.metadata["release_date"] # '1992-10-15'
67
+
68
+ st # prints every column, edge, and metadata key
69
+ ```
70
+
71
+ <details>
72
+ <summary>Output of <code>st</code></summary>
73
+
74
+ ```text
75
+ <Structure atoms=4004 residues=976 chains=12>
76
+ atoms
77
+ name <U3
78
+ element <U1
79
+ altloc <U1
80
+ occupancy float64
81
+ b_factor float64
82
+ charge int64
83
+ xyz float64 (3,)
84
+ edges
85
+ bond 3280 edges
86
+ order int64
87
+ aromatic bool
88
+ struct_conn 0 edges
89
+ type <U1
90
+ order int64
91
+ residues
92
+ name <U3
93
+ label_seq_id int64
94
+ auth_seq_id <U3
95
+ ins_code <U1
96
+ comp_type <U17
97
+ chains
98
+ label_asym_id <U2
99
+ auth_asym_id <U2
100
+ entity_id <U1
101
+ entity_type <U11
102
+ polymer_type <U14
103
+ description <U32
104
+ metadata
105
+ id '1STP'
106
+ title 'STRUCTURAL ORIGINS OF HIGH-AFFINITY BIOTIN BINDING TO STREPTAVIDIN'
107
+ keywords 'BIOTIN BINDING PROTEIN'
108
+ deposit_date '1992-03-12'
109
+ methods ['X-RAY DIFFRACTION']
110
+ authors ['Weber, P.C.', 'Salemme, F.R.']
111
+ resolution 2.6
112
+ release_date '1992-10-15'
113
+ model 1
114
+ models [1]
115
+ assembly '1'
116
+ assemblies ['1']
117
+ ```
118
+
119
+ </details>
120
+
121
+ ### Read and write
122
+
123
+ ```python
124
+ ensemble = ciffer.fetch("1l2y", directory="data", model="all") # cached in data/
125
+ len(ensemble) # 38
126
+ ciffer.write(ensemble[0], "trp_cage.pdb.gz")
127
+ ciffer.read("trp_cage.pdb.gz").atoms.xyz.shape # (304, 3)
128
+ ```
129
+
130
+ `read` takes `.cif`, `.mmcif`, `.pdb`, and `.ent`, gzipped or not. `fetch` also takes extended ids such as `pdb_00001stp`. Both accept `model`, `altloc`, and `assembly`.
131
+
132
+ ### Select and navigate
133
+
134
+ Select rows with a mask, hop between levels, and `extract()` what you keep:
135
+
136
+ ```python
137
+ import numpy as np
138
+
139
+ biotin = st.residues[st.residues.name == "BTN"].atoms
140
+ protein = st.chains[st.chains.entity_type == "polymer"].atoms
141
+ distance = np.linalg.norm(protein.xyz[:, None] - biotin.xyz, axis=-1).min(axis=1)
142
+ pocket = protein[distance < 5].residues
143
+ pocket.name # ['ASN', 'LEU', 'SER', 'TYR', 'SER', 'VAL', ...]
144
+ pocket.chains.auth_asym_id # ['A1', 'A2', 'A3', 'A4']
145
+ ciffer.write(pocket.extract(), "pocket.cif")
146
+ ```
147
+
148
+ ### Label and edit
149
+
150
+ Add your own column with `[]`, select with it, and edit through the whole level:
151
+
152
+ ```python
153
+ st.atoms["pocket"] = np.isin(st.atoms.indices, pocket.atoms.indices)
154
+ ca = st.atoms[st.atoms.name == "CA"]
155
+ len(ca[ca["pocket"]]) # 72
156
+ noise = np.random.default_rng(0).normal(scale=0.5, size=(len(pocket.atoms), 3))
157
+ st.atoms.xyz[pocket.atoms.indices] += noise # writes into the structure
158
+ # A selection such as `ca` holds copies, so `ca.xyz += 1` raises a TypeError.
159
+ ```
160
+
161
+ ### Save and load
162
+
163
+ Store a structure as bytes in any database, such as SQLite, and load it back:
164
+
165
+ ```python
166
+ import sqlite3
167
+
168
+ db = sqlite3.connect("structures.db")
169
+ db.execute("CREATE TABLE IF NOT EXISTS structures (id TEXT PRIMARY KEY, data BLOB)")
170
+ db.execute("REPLACE INTO structures VALUES (?, ?)", ("1stp", st.to_bytes()))
171
+ db.commit()
172
+
173
+ (data,) = db.execute("SELECT data FROM structures WHERE id = '1stp'").fetchone()
174
+ st = ciffer.Structure.from_bytes(data)
175
+ int(st.atoms["pocket"].sum()) # 616
176
+ len(st.atoms.bond) # 3280
177
+ st.metadata["resolution"] # 2.6
178
+ ```
179
+
180
+ Your column, the bonds, and the metadata all come back.
ciffer-0.1.0/README.md ADDED
@@ -0,0 +1,156 @@
1
+ # ciffer
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/ciffer)](https://pypi.org/project/ciffer/) [![Tests](https://github.com/Buddha7771/ciffer/actions/workflows/test.yml/badge.svg)](https://github.com/Buddha7771/ciffer/actions/workflows/test.yml)
4
+
5
+ Biomolecular structures as NumPy tables, ready for ML pipelines.
6
+
7
+ Every structure is three linked tables (atoms, residues, and chains) whose columns are NumPy arrays. Built on [gemmi](https://github.com/project-gemmi/gemmi).
8
+
9
+ - **Read and write in one line.** mmCIF and PDB, with models, altlocs, and assemblies chosen as you read.
10
+ - **Navigate like PyMOL.** Select atoms, hop to their residues and chains, and extract what you keep.
11
+ - **Handle columns like pandas.** Every column is a NumPy array, and your own columns go in with `[]`.
12
+ - **Save once, load as is.** `to_bytes()` keeps every column, bond, and metadata entry.
13
+
14
+ ## Installation
15
+
16
+ ```sh
17
+ pip install ciffer
18
+ ```
19
+
20
+ ciffer needs Python 3.11 or newer.
21
+
22
+ ## Usage
23
+
24
+ ### A first look
25
+
26
+ ```python
27
+ import ciffer
28
+
29
+ st = ciffer.fetch("1stp", assembly=True) # from RCSB, as the biological tetramer
30
+
31
+ st.atoms.name[:4] # ['N', 'CA', 'C', 'O']
32
+ st.atoms.xyz.shape # (4004, 3)
33
+ len(st.atoms.bond) # 3280
34
+
35
+ st.residues.name[:4] # ['ASP', 'PRO', 'SER', 'LYS']
36
+ st.residues.label_seq_id[:4] # [1, 2, 3, 4]
37
+
38
+ st.chains.label_asym_id[:3] # ['A1', 'B1', 'C1']
39
+ st.chains.entity_type[:3] # ['polymer', 'non-polymer', 'water']
40
+
41
+ st.metadata["resolution"] # 2.6
42
+ st.metadata["release_date"] # '1992-10-15'
43
+
44
+ st # prints every column, edge, and metadata key
45
+ ```
46
+
47
+ <details>
48
+ <summary>Output of <code>st</code></summary>
49
+
50
+ ```text
51
+ <Structure atoms=4004 residues=976 chains=12>
52
+ atoms
53
+ name <U3
54
+ element <U1
55
+ altloc <U1
56
+ occupancy float64
57
+ b_factor float64
58
+ charge int64
59
+ xyz float64 (3,)
60
+ edges
61
+ bond 3280 edges
62
+ order int64
63
+ aromatic bool
64
+ struct_conn 0 edges
65
+ type <U1
66
+ order int64
67
+ residues
68
+ name <U3
69
+ label_seq_id int64
70
+ auth_seq_id <U3
71
+ ins_code <U1
72
+ comp_type <U17
73
+ chains
74
+ label_asym_id <U2
75
+ auth_asym_id <U2
76
+ entity_id <U1
77
+ entity_type <U11
78
+ polymer_type <U14
79
+ description <U32
80
+ metadata
81
+ id '1STP'
82
+ title 'STRUCTURAL ORIGINS OF HIGH-AFFINITY BIOTIN BINDING TO STREPTAVIDIN'
83
+ keywords 'BIOTIN BINDING PROTEIN'
84
+ deposit_date '1992-03-12'
85
+ methods ['X-RAY DIFFRACTION']
86
+ authors ['Weber, P.C.', 'Salemme, F.R.']
87
+ resolution 2.6
88
+ release_date '1992-10-15'
89
+ model 1
90
+ models [1]
91
+ assembly '1'
92
+ assemblies ['1']
93
+ ```
94
+
95
+ </details>
96
+
97
+ ### Read and write
98
+
99
+ ```python
100
+ ensemble = ciffer.fetch("1l2y", directory="data", model="all") # cached in data/
101
+ len(ensemble) # 38
102
+ ciffer.write(ensemble[0], "trp_cage.pdb.gz")
103
+ ciffer.read("trp_cage.pdb.gz").atoms.xyz.shape # (304, 3)
104
+ ```
105
+
106
+ `read` takes `.cif`, `.mmcif`, `.pdb`, and `.ent`, gzipped or not. `fetch` also takes extended ids such as `pdb_00001stp`. Both accept `model`, `altloc`, and `assembly`.
107
+
108
+ ### Select and navigate
109
+
110
+ Select rows with a mask, hop between levels, and `extract()` what you keep:
111
+
112
+ ```python
113
+ import numpy as np
114
+
115
+ biotin = st.residues[st.residues.name == "BTN"].atoms
116
+ protein = st.chains[st.chains.entity_type == "polymer"].atoms
117
+ distance = np.linalg.norm(protein.xyz[:, None] - biotin.xyz, axis=-1).min(axis=1)
118
+ pocket = protein[distance < 5].residues
119
+ pocket.name # ['ASN', 'LEU', 'SER', 'TYR', 'SER', 'VAL', ...]
120
+ pocket.chains.auth_asym_id # ['A1', 'A2', 'A3', 'A4']
121
+ ciffer.write(pocket.extract(), "pocket.cif")
122
+ ```
123
+
124
+ ### Label and edit
125
+
126
+ Add your own column with `[]`, select with it, and edit through the whole level:
127
+
128
+ ```python
129
+ st.atoms["pocket"] = np.isin(st.atoms.indices, pocket.atoms.indices)
130
+ ca = st.atoms[st.atoms.name == "CA"]
131
+ len(ca[ca["pocket"]]) # 72
132
+ noise = np.random.default_rng(0).normal(scale=0.5, size=(len(pocket.atoms), 3))
133
+ st.atoms.xyz[pocket.atoms.indices] += noise # writes into the structure
134
+ # A selection such as `ca` holds copies, so `ca.xyz += 1` raises a TypeError.
135
+ ```
136
+
137
+ ### Save and load
138
+
139
+ Store a structure as bytes in any database, such as SQLite, and load it back:
140
+
141
+ ```python
142
+ import sqlite3
143
+
144
+ db = sqlite3.connect("structures.db")
145
+ db.execute("CREATE TABLE IF NOT EXISTS structures (id TEXT PRIMARY KEY, data BLOB)")
146
+ db.execute("REPLACE INTO structures VALUES (?, ?)", ("1stp", st.to_bytes()))
147
+ db.commit()
148
+
149
+ (data,) = db.execute("SELECT data FROM structures WHERE id = '1stp'").fetchone()
150
+ st = ciffer.Structure.from_bytes(data)
151
+ int(st.atoms["pocket"].sum()) # 616
152
+ len(st.atoms.bond) # 3280
153
+ st.metadata["resolution"] # 2.6
154
+ ```
155
+
156
+ Your column, the bonds, and the metadata all come back.
@@ -0,0 +1,61 @@
1
+ [project]
2
+ name = "ciffer"
3
+ version = "0.1.0"
4
+ description = "Biomolecular structures as NumPy tables, ready for ML pipelines."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ requires-python = ">=3.11"
8
+ authors = [{ name = "Howon Lee", email = "hwlee7771@gmail.com" }]
9
+ keywords = ["mmcif", "pdb", "protein", "structure", "numpy", "machine-learning"]
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Intended Audience :: Science/Research",
13
+ "Programming Language :: Python :: 3.11",
14
+ "Programming Language :: Python :: 3.12",
15
+ "Programming Language :: Python :: 3.13",
16
+ "Programming Language :: Python :: 3.14",
17
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
18
+ "Typing :: Typed",
19
+ ]
20
+ dependencies = ["gemmi>=0.7.5", "numpy>=2.2", "zstandard>=0.25.0"]
21
+
22
+ [project.urls]
23
+ Repository = "https://github.com/Buddha7771/ciffer"
24
+ Issues = "https://github.com/Buddha7771/ciffer/issues"
25
+
26
+ [dependency-groups]
27
+ dev = ["pre-commit>=4.6", "pytest>=9.0.3", "ruff==0.17.0", "ty==0.0.88"]
28
+
29
+ [build-system]
30
+ requires = ["hatchling"]
31
+ build-backend = "hatchling.build"
32
+
33
+ [tool.hatch.build.targets.wheel]
34
+ packages = ["src/ciffer"]
35
+
36
+ [tool.ruff]
37
+ line-length = 88
38
+ target-version = "py311"
39
+
40
+ [tool.ruff.lint]
41
+ select = ["ALL"]
42
+ extend-select = [
43
+ "D417",
44
+ ] # Disabled by the numpy convention; keep Parameters complete
45
+ ignore = [
46
+ "COM812", # Conflicts with ruff formatter
47
+ "CPY001", # Missing copyright notice
48
+ "D100", # Missing docstring in public module
49
+ "D104", # Missing docstring in public package
50
+ "ANN401", # Dynamically typed expressions (typing.Any)
51
+ "PLR0913", # Too many arguments in function definition
52
+ ]
53
+
54
+ [tool.ruff.lint.per-file-ignores]
55
+ "tests/*" = ["ANN201", "D", "INP001", "PLR2004", "S101"]
56
+
57
+ [tool.ruff.lint.pydocstyle]
58
+ convention = "numpy"
59
+
60
+ [tool.pytest.ini_options]
61
+ testpaths = ["tests"]
@@ -0,0 +1,21 @@
1
+ from .cif import fetch, read, write
2
+ from .structure import Structure, concat
3
+ from .table import EdgeList, Table
4
+ from .view import AtomView, Bond, ChainView, Level, ResidueView, StructConn, View
5
+
6
+ __all__ = [
7
+ "AtomView",
8
+ "Bond",
9
+ "ChainView",
10
+ "EdgeList",
11
+ "Level",
12
+ "ResidueView",
13
+ "StructConn",
14
+ "Structure",
15
+ "Table",
16
+ "View",
17
+ "concat",
18
+ "fetch",
19
+ "read",
20
+ "write",
21
+ ]