Skip to content

Commit bb74478

Browse files
committed
Add migration documentation for 0.x -> 1.0
Fixes #181
1 parent 854c12f commit bb74478

File tree

4 files changed

+138
-2
lines changed

4 files changed

+138
-2
lines changed

doc/advanced/migration.rst

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
===============
2+
From 0.x to 1.0
3+
===============
4+
5+
Don't Touch A Thing
6+
===================
7+
8+
The first and simplest way to transition is to not transition: the 0.x
9+
API won't be removed for a long time, possibly ever. While it is
10+
unlikely to get updated any further and will eventually (hopefully?)
11+
fall behind, if you can't be arsed you probably don't have to until an
12+
unlikely 2.0.
13+
14+
Unavoidable Divergences
15+
=======================
16+
17+
Although the 1.0 API aims to be reasonably bridge-able to
18+
0.x-compatible code, a few items may be cause for concern and require
19+
special attention:
20+
21+
- The 1.0 API supports :data:`ua_parser.UserAgent.patch_minor
22+
<ua_parser.UserAgent>`, which may be a concern if the program stores
23+
match results and compares them exactly.
24+
- The global parser of the 1.0 API is instantiated lazily on-demand,
25+
this may cause unexpected runtime loads and can be remediated by
26+
explicitly accessing the parser on load e.g.::
27+
28+
import ua_parser
29+
# force initialisation of global parser
30+
ua_parser.parser
31+
32+
- The 1.0 API defaults to an :class:`re2-based parser
33+
<ua_parser.re2.Resolver>` if |re2|_ is installed, although it seems
34+
unlikely you may wish to consider replacing it with configuring a
35+
:class:`~ua_parser.Parser` with a :class:`ua_parser.basic.Resolver`
36+
if |re2|_ is one of your dependencies.
37+
38+
Default Ruleset
39+
===============
40+
41+
While the 1.0 API was designed to better respect :pep:`8` and support
42+
:mod:`typing`, it was also designed to easily be transitioned from.
43+
44+
Given a 0.x API not using YAML, the conversion should be very easy and
45+
consists of:
46+
47+
- updating the import from ``ua_parser.user_agent_parser`` to just
48+
``ua_parser``
49+
- lowercasing the function names
50+
- adding :meth:`~ua_parser.Result.with_defaults()` after the function
51+
call
52+
- wrapping the entire thing in :func:`dataclasses.asdict`
53+
54+
For example, given
55+
56+
..
57+
>>> from pprint import pprint
58+
>>> ua_string = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36'
59+
60+
.. code-block:: pycon
61+
62+
>>> from ua_parser import user_agent_parser
63+
>>> pprint(user_agent_parser.Parse(ua_string)) # doctest: +NORMALIZE_WHITESPACE
64+
{'device': {'brand': 'Apple', 'family': 'Mac', 'model': 'Mac'},
65+
'os': {'family': 'Mac OS X',
66+
'major': '10',
67+
'minor': '9',
68+
'patch': '4',
69+
'patch_minor': None},
70+
'string': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 '
71+
'(KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36',
72+
'user_agent': {'family': 'Chrome',
73+
'major': '41',
74+
'minor': '0',
75+
'patch': '2272'}}
76+
77+
the 1.0 version would be:
78+
79+
.. code-block:: pycon
80+
81+
>>> import dataclasses
82+
>>> import ua_parser
83+
>>> pprint(dataclasses.asdict(ua_parser.parse(ua_string).with_defaults())) # doctest: +NORMALIZE_WHITESPACE
84+
{'device': {'brand': 'Apple', 'family': 'Mac', 'model': 'Mac'},
85+
'os': {'family': 'Mac OS X',
86+
'major': '10',
87+
'minor': '9',
88+
'patch': '4',
89+
'patch_minor': None},
90+
'string': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 '
91+
'(KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36',
92+
'user_agent': {'family': 'Chrome',
93+
'major': '41',
94+
'minor': '0',
95+
'patch': '2272',
96+
'patch_minor': '104'}}
97+
98+
.. note::
99+
100+
- by default, the 1.0 API simply leaves entries ``None`` when no
101+
data was matched, :meth:`~ua_parser.Result.with_defaults()`
102+
fills them with the default value for the domain matching the 0.x API
103+
- the 1.0 API returns :class:`typed dataclasses rather than untyped
104+
dicts <ua_parser.core.UserAgent>`, hence the necessary conversion
105+
to dict
106+
107+
YAML Ruleset
108+
============
109+
110+
The 1.0 API does not support :envvar:`UA_PARSER_YAML` anymore, instead
111+
it provides a layered API which lets clients use multiple parsers at
112+
the same time, and load rulesets from various datasources.
113+
114+
Legacy YAML support can be added via a pretty small shim::
115+
116+
import ua_parser
117+
from ua_parser.loaders import load_yaml
118+
119+
if yaml_path = os.environ.get("UA_PARSER_YAML"):
120+
ua_parser.parser = ua_parser.Parser.from_matchers(
121+
load_yaml(yaml_path))
122+
123+
This will load the YAML file, create a parser from it, and set the new
124+
parser as the global parser used by the top-level utility functions.
125+
126+
.. seealso::
127+
128+
- :ref:`guide-custom-rulesets`
129+
- :ref:`guide-custom-global-parser`
130+
- :ref:`api-loading`
131+

doc/api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Base Resolvers
5959
--------------
6060

6161
Base resolvers take sets of :class:`~ua_parser.core.Matchers`
62-
generated by :ref:`loaders <Loading>`, and use them to extract data
62+
generated by :ref:`loaders <api-loading>`, and use them to extract data
6363
from user agent strings.
6464

6565
.. autoclass:: ua_parser.basic.Resolver(Matchers)
@@ -129,7 +129,7 @@ basic resolver <ua_parser.basic.Resolver>`.
129129

130130
.. autoclass:: Local
131131

132-
.. _loading:
132+
.. _api-loading:
133133

134134
Loading
135135
-------

doc/guides.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
Guides
33
======
44

5+
.. _guide-custom-rulesets:
6+
57
Custom Rulesets
68
===============
79

@@ -36,6 +38,8 @@ ua-parser provides easy ways to load custom rolesets:
3638
parser = Parser.from_matchers(load_yaml("regexes.yaml"))
3739
parser.parse(some_ua)
3840
41+
.. _guide-custom-global-parser:
42+
3943
Custom Global Parser
4044
====================
4145

doc/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ For more detailed insight and advanced uses, see the :doc:`api` and
1717
guides
1818
api
1919
advanced/caches
20+
advanced/migration

0 commit comments

Comments
 (0)