|
1 | 1 | #!/usr/bin/env python |
2 | 2 | # flake8: noqa |
3 | | -import os |
4 | | -from distutils import log |
5 | | -from distutils.core import Command |
6 | | -from distutils.command.build import build as _build |
7 | | -from setuptools import setup, find_packages |
8 | | -from setuptools.command.develop import develop as _develop |
9 | | -from setuptools.command.sdist import sdist as _sdist |
10 | | -from setuptools.command.install import install as _install |
11 | | - |
12 | | - |
13 | | -def check_output(*args, **kwargs): |
14 | | - from subprocess import Popen |
15 | | - |
16 | | - proc = Popen(*args, **kwargs) |
17 | | - output, _ = proc.communicate() |
18 | | - rv = proc.poll() |
19 | | - assert rv == 0, output |
20 | | - |
21 | | - |
22 | | -class build_regexes(Command): |
23 | | - description = "build supporting regular expressions from uap-core" |
24 | | - user_options = [ |
25 | | - ("work-path=", "w", "The working directory for source files. Defaults to ."), |
26 | | - ("build-lib=", "b", "directory for script runtime modules"), |
27 | | - ( |
28 | | - "inplace", |
29 | | - "i", |
30 | | - "ignore build-lib and put compiled javascript files into the source " |
31 | | - + "directory alongside your pure Python modules", |
32 | | - ), |
33 | | - ( |
34 | | - "force", |
35 | | - "f", |
36 | | - "Force rebuilding of static content. Defaults to rebuilding on version " |
37 | | - "change detection.", |
38 | | - ), |
39 | | - ] |
40 | | - boolean_options = ["force"] |
41 | | - |
42 | | - def initialize_options(self): |
43 | | - self.build_lib = None |
44 | | - self.force = None |
45 | | - self.work_path = None |
46 | | - self.inplace = None |
47 | | - |
48 | | - def finalize_options(self): |
49 | | - install = self.distribution.get_command_obj("install") |
50 | | - sdist = self.distribution.get_command_obj("sdist") |
51 | | - build_ext = self.distribution.get_command_obj("build_ext") |
52 | | - |
53 | | - if self.inplace is None: |
54 | | - self.inplace = ( |
55 | | - (build_ext.inplace or install.finalized or sdist.finalized) and 1 or 0 |
56 | | - ) |
| 3 | +from contextlib import suppress |
| 4 | +from os import fspath |
| 5 | +from pathlib import Path |
| 6 | +from typing import Optional, List, Dict |
57 | 7 |
|
58 | | - if self.inplace: |
59 | | - self.build_lib = "./src" |
60 | | - else: |
61 | | - self.set_undefined_options("build", ("build_lib", "build_lib")) |
62 | | - if self.work_path is None: |
63 | | - self.work_path = os.path.realpath(os.path.join(os.path.dirname(__file__))) |
| 8 | +from setuptools import setup, Command, find_namespace_packages |
| 9 | +from setuptools.command.build import build, SubCommand |
| 10 | +from setuptools.command.editable_wheel import editable_wheel |
| 11 | + |
| 12 | +import yaml |
| 13 | + |
| 14 | + |
| 15 | +build.sub_commands.insert(0, ("compile-regexes", None)) |
| 16 | + |
| 17 | + |
| 18 | +class CompileRegexes(Command, SubCommand): |
| 19 | + def initialize_options(self) -> None: |
| 20 | + self.pkg_name: Optional[str] = None |
64 | 21 |
|
65 | | - def run(self): |
| 22 | + def finalize_options(self) -> None: |
| 23 | + self.pkg_name = self.distribution.get_name().replace("-", "_") |
| 24 | + |
| 25 | + def get_source_files(self) -> List[str]: |
| 26 | + return ["uap-core/regexes.yaml"] |
| 27 | + |
| 28 | + def get_outputs(self) -> List[str]: |
| 29 | + return [f"{self.pkg_name}/_regexes.py"] |
| 30 | + |
| 31 | + def get_output_mapping(self) -> Dict[str, str]: |
| 32 | + return dict(zip(self.get_source_files(), self.get_outputs())) |
| 33 | + |
| 34 | + def run(self) -> None: |
| 35 | + # FIXME: check git / submodules? |
| 36 | + """ |
66 | 37 | work_path = self.work_path |
67 | 38 | if not os.path.exists(os.path.join(work_path, ".git")): |
68 | 39 | return |
69 | 40 |
|
70 | 41 | log.info("initializing git submodules") |
71 | 42 | check_output(["git", "submodule", "init"], cwd=work_path) |
72 | 43 | check_output(["git", "submodule", "update"], cwd=work_path) |
| 44 | + """ |
| 45 | + if not self.pkg_name: |
| 46 | + return # or error? |
73 | 47 |
|
74 | | - yaml_src = os.path.join(work_path, "uap-core", "regexes.yaml") |
75 | | - if not os.path.exists(yaml_src): |
| 48 | + yaml_src = Path("uap-core", "regexes.yaml") |
| 49 | + if not yaml_src.is_file(): |
76 | 50 | raise RuntimeError( |
77 | | - "Unable to find regexes.yaml, should be at %r" % yaml_src |
| 51 | + f"Unable to find regexes.yaml, should be at {yaml_src!r}" |
78 | 52 | ) |
79 | 53 |
|
80 | | - def force_bytes(text): |
81 | | - if text is None: |
82 | | - return text |
83 | | - return text.encode("utf8") |
84 | | - |
85 | 54 | def write_params(fields): |
86 | 55 | # strip trailing None values |
87 | 56 | while len(fields) > 1 and fields[-1] is None: |
88 | 57 | fields.pop() |
89 | 58 |
|
90 | 59 | for field in fields: |
91 | | - fp.write((" %r,\n" % field).encode("utf-8")) |
| 60 | + fp.write((f" {field!r},\n").encode()) |
| 61 | + |
| 62 | + with yaml_src.open("rb") as f: |
| 63 | + regexes = yaml.safe_load(f) |
92 | 64 |
|
93 | | - import yaml |
| 65 | + if self.editable_mode: |
| 66 | + dist_dir = Path("src") |
| 67 | + else: |
| 68 | + dist_dir = Path(self.get_finalized_command("bdist_wheel").bdist_dir) |
94 | 69 |
|
95 | | - log.info("compiling regexes.yaml -> _regexes.py") |
96 | | - with open(yaml_src, "rb") as fp: |
97 | | - regexes = yaml.safe_load(fp) |
| 70 | + outdir = dist_dir / self.pkg_name |
| 71 | + outdir.mkdir(parents=True, exist_ok=True) |
98 | 72 |
|
99 | | - lib_dest = os.path.join(self.build_lib, "ua_parser") |
100 | | - if not os.path.exists(lib_dest): |
101 | | - os.makedirs(lib_dest) |
| 73 | + dest = outdir / "_regexes.py" |
102 | 74 |
|
103 | | - py_dest = os.path.join(lib_dest, "_regexes.py") |
104 | | - with open(py_dest, "wb") as fp: |
| 75 | + with dest.open("wb") as fp: |
105 | 76 | # fmt: off |
106 | 77 | fp.write(b"# -*- coding: utf-8 -*-\n") |
107 | | - fp.write(b"############################################\n") |
108 | | - fp.write(b"# NOTICE: This file is autogenerated from #\n") |
109 | | - fp.write(b"# regexes.yaml. Do not edit by hand, #\n") |
110 | | - fp.write(b"# instead, re-run `setup.py build_regexes` #\n") |
111 | | - fp.write(b"############################################\n") |
| 78 | + fp.write(b"########################################################\n") |
| 79 | + fp.write(b"# NOTICE: This file is autogenerated from regexes.yaml #\n") |
| 80 | + fp.write(b"########################################################\n") |
112 | 81 | fp.write(b"\n") |
113 | 82 | fp.write(b"from .user_agent_parser import (\n") |
114 | 83 | fp.write(b" UserAgentParser, DeviceParser, OSParser,\n") |
@@ -156,77 +125,9 @@ def write_params(fields): |
156 | 125 | fp.write(b"]\n") |
157 | 126 | # fmt: on |
158 | 127 |
|
159 | | - self.update_manifest() |
160 | | - |
161 | | - def update_manifest(self): |
162 | | - sdist = self.distribution.get_command_obj("sdist") |
163 | | - if not sdist.finalized: |
164 | | - return |
165 | | - |
166 | | - sdist.filelist.files.append("src/ua_parser/_regexes.py") |
167 | | - |
168 | | - |
169 | | -class develop(_develop): |
170 | | - def run(self): |
171 | | - self.run_command("build_regexes") |
172 | | - _develop.run(self) |
173 | | - |
174 | | - |
175 | | -class install(_install): |
176 | | - def run(self): |
177 | | - self.run_command("build_regexes") |
178 | | - _install.run(self) |
179 | | - |
180 | | - |
181 | | -class build(_build): |
182 | | - def run(self): |
183 | | - self.run_command("build_regexes") |
184 | | - _build.run(self) |
185 | | - |
186 | | - |
187 | | -class sdist(_sdist): |
188 | | - sub_commands = _sdist.sub_commands + [("build_regexes", None)] |
189 | | - |
190 | | - |
191 | | -cmdclass = { |
192 | | - "sdist": sdist, |
193 | | - "develop": develop, |
194 | | - "build": build, |
195 | | - "install": install, |
196 | | - "build_regexes": build_regexes, |
197 | | -} |
198 | | - |
199 | 128 |
|
200 | 129 | setup( |
201 | | - name="ua-parser", |
202 | | - version="0.16.1", |
203 | | - description="Python port of Browserscope's user agent parser", |
204 | | - author="PBS", |
205 | | - author_email="no-reply@pbs.org", |
206 | | - packages=find_packages(where="src"), |
207 | | - package_dir={"": "src"}, |
208 | | - license="Apache 2.0", |
209 | | - zip_safe=False, |
210 | | - url="https://github.com/ua-parser/uap-python", |
211 | | - include_package_data=True, |
212 | | - setup_requires=["pyyaml"], |
213 | | - install_requires=[], |
214 | | - cmdclass=cmdclass, |
215 | | - classifiers=[ |
216 | | - "Development Status :: 4 - Beta", |
217 | | - "Environment :: Web Environment", |
218 | | - "Intended Audience :: Developers", |
219 | | - "Operating System :: OS Independent", |
220 | | - "License :: OSI Approved :: Apache Software License", |
221 | | - "Programming Language :: Python", |
222 | | - "Topic :: Internet :: WWW/HTTP", |
223 | | - "Topic :: Software Development :: Libraries :: Python Modules", |
224 | | - "Programming Language :: Python", |
225 | | - "Programming Language :: Python :: 3.8", |
226 | | - "Programming Language :: Python :: 3.9", |
227 | | - "Programming Language :: Python :: 3.10", |
228 | | - "Programming Language :: Python :: 3.11", |
229 | | - "Programming Language :: Python :: Implementation :: CPython", |
230 | | - "Programming Language :: Python :: Implementation :: PyPy", |
231 | | - ], |
| 130 | + cmdclass={ |
| 131 | + "compile-regexes": CompileRegexes, |
| 132 | + } |
232 | 133 | ) |
0 commit comments