| 158 | |
| 159 | |
| 160 | class PandasDocstring(Validator): |
| 161 | def __init__(self, func_name: str, doc_obj=None) -> None: |
| 162 | self.func_name = func_name |
| 163 | if doc_obj is None: |
| 164 | doc_obj = get_doc_object(Validator._load_obj(func_name)) |
| 165 | super().__init__(doc_obj) |
| 166 | |
| 167 | @property |
| 168 | def name(self): |
| 169 | return self.func_name |
| 170 | |
| 171 | @property |
| 172 | def mentioned_private_classes(self): |
| 173 | return [klass for klass in PRIVATE_CLASSES if klass in self.raw_doc] |
| 174 | |
| 175 | @property |
| 176 | def examples_source_code(self): |
| 177 | lines = doctest.DocTestParser().get_examples(self.raw_doc) |
| 178 | return [line.source for line in lines] |
| 179 | |
| 180 | def validate_pep8(self): |
| 181 | if not self.examples: |
| 182 | return |
| 183 | |
| 184 | # F401 is needed to not generate flake8 errors in examples |
| 185 | # that do not user numpy or pandas |
| 186 | content = "".join( |
| 187 | ( |
| 188 | "import numpy as np # noqa: F401\n", |
| 189 | "import pandas as pd # noqa: F401\n", |
| 190 | *self.examples_source_code, |
| 191 | ) |
| 192 | ) |
| 193 | |
| 194 | error_messages = [] |
| 195 | |
| 196 | file = tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", delete=False) |
| 197 | try: |
| 198 | file.write(content) |
| 199 | file.flush() |
| 200 | cmd = [ |
| 201 | sys.executable, |
| 202 | "-m", |
| 203 | "flake8", |
| 204 | "--format=%(row)d\t%(col)d\t%(code)s\t%(text)s", |
| 205 | "--max-line-length=88", |
| 206 | "--ignore=E203,E3,W503,W504,E402,E731,E128,E124,E704", |
| 207 | file.name, |
| 208 | ] |
| 209 | response = subprocess.run(cmd, capture_output=True, check=False, text=True) |
| 210 | for output in ("stdout", "stderr"): |
| 211 | out = getattr(response, output) |
| 212 | out = out.replace(file.name, "") |
| 213 | messages = out.strip("\n").splitlines() |
| 214 | if messages: |
| 215 | error_messages.extend(messages) |
| 216 | finally: |
| 217 | file.close() |